STIG Help

Check and align analysis evidence

Use stigCheckAnalysis for one workflow: resolve analysis configuration, review each activity's transforms, and align sink results from the initial LLVM module through the final HTML report. The default mode collects the full chain; --configuration-only stops at P5. These are modes of the same task.

The task collects available structured evidence, including after a producer failure. Diagnostic producers apply the configured failAt; a CRITICAL finding does not independently override failAt=none in the configuration evidence check. An execution error that prevents a producer from doing its job still fails that producer. The final evidence collector succeeds when it saves the requested evidence, even when that evidence records failures or omissions; it fails when it cannot perform collection, such as writing the requested ZIP. Gradle still reports failed producer tasks as build failures. A successful collector does not automatically prove semantic agreement across every LLVM checkpoint, approve a transform, or accept a software defect. The staged review below is how a person and $stig:source-analysis establish that stronger completion claim.

Missing referenced P5 implementations and unfinished transform reviews are HIGH findings. With failAt=CRITICAL they permit P6/P7 and evidence collection without --continue. Results remain provisional: opaque calls can hide data, control, and memory effects, so an empty flow result does not prove that the original program has no flow. analysis/provisional_analysis.json records exact missing symbols and sets evidenceReady=false; generated reports display the limitation. Invalid LLVM, failed tools, and required run-plan symbols absent even as declarations are execution defects. Merely changing a finding's severity does not make those defects executable.

The Glossary defines the terms used by the generated analysis_review.md, including P3 bitcode, P5 rewrite applications, problem groups, and problem severity. Explain each finding by naming the artifact or Gradle build script, the affected function or rule, and the value or code condition that is wrong.

Portable replay status: P6 replay is supported by stigReplayArchivedAnalyzerRun when the required captured run evidence is present. Portable P3/P5 reconstruction and P7/HTML replay still need implementation. Configuration-only ZIPs cannot use the existing P6 replay. See Stage 3 for the distinction between reviewing LLVM, applying post-link rewrites, and reconstructing a stage from its compilation inputs.

Choose the collection mode

Invocation

Requested dependency chain

Root archive with --zip, all modules

stigCheckAnalysis --configuration-only

P1–P5 configuration and transform evidence; no P6, P7, or report

<project>-analysis-configuration-evidence-all.zip

stigCheckAnalysis

Configuration evidence plus each selected module's stigGenerateHtml chain, P6, and P7

<project>-analysis-evidence-all.zip

For one activity, run from the consumer root:

./gradlew :activities:my_activity:stigCheckAnalysis --configuration-only --zip --console=plain --info ./gradlew :activities:my_activity:stigCheckAnalysis --zip --console=plain --info

Choose the first command for configuration evidence and the second when collecting downstream evidence. Omit --zip for local structured output. The root stigCheckAnalysis selects all eligible source-analysis modules by default. Select a subset using exact Gradle project paths; a comma-separated value or repeated --modules options are supported. The project defines these names: activities, components, and other hierarchies are equally valid.

./gradlew :stigCheckAnalysis --configuration-only --zip --console=plain --info ./gradlew :stigCheckAnalysis --modules=:components:one,:components:two --zip --console=plain --info ./gradlew :stigCheckAnalysis --modules=:components:one --zip --zip-directory=../exchange --console=plain --info

Use the leading colon for root options: Gradle's unqualified stigCheckAnalysis can also select the same-named tasks in subprojects, which do not own --modules. Selection controls the dependency chains and collection membership. Unselected modules are not analyzed or exported; their existing review state is preserved. Existing confirmed modules need review again if a shared rule or relevant input changes. Unknown, duplicate, blank, or ineligible selections fail explicitly.

Root export writes one self-contained ZIP containing the selected modules and stores identical content once. Default destination: ../<root-project-name>-check-analysis-evidence/. Use --zip-directory for an absolute path or one relative to the consumer root; it requires --zip. Gradle task options do not support an optional value on a Boolean switch, so --zip ../exchange is not the syntax. STIG creates the destination if needed and atomically replaces only the ZIP for that mode and module selection after checking the written payloads. Unrelated exchange files remain intact. A subset's filename uses a stable hash of its sorted module paths instead of all, so different subsets and full/configuration modes coexist. Direct module checks export a one-module collection in the same format. The final summary prints each generated ZIP's absolute path, bytes, MiB, encryption state, and total size.

Local structured evidence remains in the selected module's normal task output directory, for example:

activities/my_activity/build/stig/stigCheckAnalysis/

The configuration diagnostic can build an expensive initial LLVM module with stigBuildFullLlvmOwnershipInventory. Normal reporting does not require that module. Gradle may reuse validated UP-TO-DATE or FROM-CACHE producer outputs. Full collection requires the activity report chain; it does not require the combined root HTML publication.

See the generated Gradle task API for exact options.

The shared Gradle logger keeps its STIG | stage | operation | event | details columns. With Gradle's colored console, CRITICAL/HIGH problems, errors, failed checks, and failed tools are red; MODERATE/LOW problems and warnings are yellow; successful checks and tools are green. Gradle controls terminal support and the palette. --console=plain produces uncolored text, and structured JSONL records never contain terminal color codes.

Read the evidence and the analysis review

Captured native objects/libraries and fingerprinted external product source/header inputs are included under compilation/libraries/. Only available paths inventoried by the captured native actions are copied. An object is a whole object file; an archive or shared library is a whole .a or .so, not just called functions or selected archive members. Identical bytes are stored once in a collection. Unavailable or changed files are recorded explicitly in library_evidence.json; the collector does not substitute local files with a different identity. Other production source snapshots are excluded. Compiled LLVM definitions, call sites, and metadata are the primary implementation evidence for portable review. Source files are not required when those artifacts establish the relevant behavior. A declaration alone generally cannot establish that behavior: obtain the missing compiled implementation or other sufficient effect evidence from the generating environment. Do not infer a transfer from its name.

The earliest archive checkpoint is the initial LLVM module, built from P2-derived compilation commands. The native executable and selected P6 module are separate artifacts. Earlier checkpoints are retained as LLVM text (.ll). Full collection additionally retains LLVM bitcode (.bc) for each selected P6 module, including slices. Assembling .ll produces bitcode for that checkpoint; it does not perform P3 selection or P5 construction.

P1 may use GCC or another configured native compiler. P2 converts the captured compilation commands to the pinned Clang/LLVM toolchain and recompiles their source inputs; it does not translate a GCC executable into LLVM. The initial LLVM module is built from those compiler inputs. A prebuilt library's implementation can still be absent from that module, leaving only a declaration even in llvm/full/module.ll. The acquisition stages are:

Stage

External source handling

Native Bazel/GCC build

Uses the configured native target and build policy. STIG's LLVM source selection does not change native linkage.

P1 compile-command extraction

Retains external/ actions and their Bazel configuration ID, checksum, isTool, and execution platform.

P2 conversion

Converts captured actions to pinned LLVM commands and preserves that provenance; it does not execute GCC output.

Initial full LLVM build

Compiles product actions, including externals; excludes configurations explicitly marked isTool=true. Records the decision in llvm/full/compile_command_selection.json.

P3/P4/P5

Continue to apply configured provenance, software-under-analysis, and analyzer-input selections. Expanded original evidence does not automatically expand the analyzed software scope.

The old P1 blanket external/ exclusion is removed. The full module still cannot contain implementations whose sources/compile actions are unavailable, including prebuilt runtime libraries. It contains compilation units, rather than the native linker's exact used-function subset. Size growth depends on those units, templates, debug information, and optimization; measure the generated .ll and compressed ZIP rather than estimating from library file size. Check the selection report and llvm/full/compiled_bitcode_index.json before attributing a gap to ZIP packaging. Native objects and libraries support symbol, linkage, and disassembly investigation; PhASAR consumes LLVM bitcode. An aquery action graph alone does not establish what linked or ran; actual native outputs and final link evidence do.

Collection schema ai.exida.stig/analysis-evidence-collection version 1 has a root evidence_manifest.json, per-module manifests under modules/<Gradle path components>/, and common payloads under shared/sha256/<hash>. Each module's files mapping resolves its original logical paths to physical ZIP storage paths; the module manifest retains its own hashes and provenance unchanged. requestedModules and unavailableModules distinguish the requested scope from modules collected in the current invocation. The audit and archived-review tasks accept collections and older single-module ZIPs. The paths in the following table are module-logical paths.

Archive path

Meaning / producing task

llvm/full/module.ll

Initial LLVM module in LLVM text, stigBuildFullLlvmOwnershipInventory, using P2-derived compilation commands

llvm/p3/module.ll

LLVM text for P3 bitcode, stigAnalysisP3BuildProvenanceBitcode

compilation/p3/, compilation/p4/, compilation/p5/

P3 provenance compilation units, P4 softwareUnderAnalysis native compilation units, and P5 compiler inputs, respectively

llvm/p5-pre-transform/module.ll

P5 input in LLVM text, stigAnalysisP5BuildUntransformedAnalyzerInput; source replacements may already have been compiled before post-link rewrites

llvm/p5/module.ll

LLVM text for final P5 bitcode from stigAnalysisP5ProduceBitcodeTransformEvidence, validated by stigAnalysisP5ApplyBitcodeTransforms

llvm/symbol_states.json

Defined, declared, absent, or rewritten function states at the LLVM checkpoints; not source-to-sink reachability verdicts

selected_p6_modules.json

Full-mode mapping from each runStem to its exact archived .bc/.ll pair and hashes

run-plan/, analysis/

P5/P6 plans, endpoint metadata, analyzer configuration and available results

p7/, transforms/, report/diagrams.md

Available presentation mappings, applied-transform evidence, and generated report input

Availability depends on the requested mode and actual completed stages. Read evidence_manifest.json for the concrete payload paths, roles, sizes, SHA-256 hashes, schema, producer version, and workflow compatibility. Verify the payloads before reviewing them. Preserve the archive and write replay results outside it. Original source-machine paths in provenance are not instructions to substitute similarly named files from another checkout.

An analysis attempt writes its live build log to the root project's build/stig/stigCheckAnalysis/gradle.log. Each collector retains an immutable logs/gradle.log snapshot with INFO messages, standard output/error, and nested task failures; --info is not required, and explicit --debug retains DEBUG messages. The companion logs/gradle-log.json records the invocation identity and capture interval. Capture starts with the analysis attempt; Gradle startup, configuration, and output after the snapshot are outside that interval. Console verbosity follows the Gradle invocation's logging flags; use --info to display INFO messages there.

The root and activity Gradle build scripts, configured topic JSON, and interface ASIL annotation JSON are authored inputs. Collection recognizes their exact configured files and archive paths without requiring a generated-output producer. When the configuration evidence index captures an input, its size and SHA-256 must still match; a changed or missing input is excluded and makes collection partial. An excluded indexed input is not recaptured using its current contents. Generated files retain their producing task's current-invocation attribution requirement.

There is no longer a generated long HANDOFF.md to fill in. Its responsibilities are split between current facts and the installed skill's procedure:

Current artifact

How to use it

README.md

Short provenance and skill entry point

review/transform_review.json

Activity status, actionCodes, actionItems, and all active activity transform rules in transformReviews, including candidate use(...) edits

review/source_code_analysis_configuration.proposed.json

Boundary, ownership, unresolved-symbol, and configuration candidate facts

review/diagnostic_status.json, task-owned problems.jsonl, P5 stage_status.json

Recorded diagnostic outcomes, problem records, and P5 validation state; use manifest paths

flow_gaps.json

Full-mode index of problematic report rows, resolved to exact LLVM sinks and analyzer runs

tabulator_tables.json

Full-mode snapshot of all captured safety-sink tables, including healthy rows

A configuration archive includes review/problems.jsonl; the generated review uses those records for its captured CRITICAL and HIGH counts. A normal configuration-only check also copies its local summaries to configuration/ beneath the activity output directory. Partial collection writes attempt metadata directly beneath that directory. A root configuration check combines activity reviews at:

build/stig/stigAggregateAnalysisConfigurationEvidence/source_code_analysis_review.json

That root JSON is a shared-rule navigation aid, not a replacement for activity evidence and not a required payload of an activity ZIP. Review JSON and candidate DSL describe facts and proposed edits; editing generated JSON or Markdown cannot confer user review.

tabulator_tables.json is extracted from the inline table JSON in generated report/diagrams.md, after the report prerequisite. It is report-input evidence, not an independent LLVM analysis or a capture of the browser's rendered page. A zero flow_gaps.json count does not establish configuration readiness or complete alignment.

Audit existing evidence before reviewing it

stigAuditAnalysisEvidence replaces repeated manifest-inspection, verification, and mechanical LLVM audit scripts. It accepts an existing ZIP, extracted archive, or local review_evidence_index.json without selecting analysis producers:

./gradlew :stigAuditAnalysisEvidence --evidence-zip=/path/to/activity.zip --console=plain --info

The audit checks schema and payload inventories, indexed supporting files, and captured pipeline/diagnostic status first. It records the captured P5/diagnostic statuses, exclusions, and repository revisions alongside that inventory. On a blocker it writes the finding and skips payload-wide hashing, LLVM extraction, and symbol indexing. When the gate passes, it verifies payload hashes and sizes, reindexes LLVM through STIG's parser, checks captured symbol indexes and original byte ranges, and reconciles P3/P5 selectors, applications, aliases, and final-body accounting through STIG's existing transform logic. Compilation inventories retain explicit counted units. These are mechanical checks; model semantics and sink agreement still require review.

The generated analysis_evidence_audit.json and .md live under build/stig/stigAuditAnalysisEvidence/, with one report per input and a combined summary. Task success means the audit report was written; read its outcome, individual check states, unavailable checks, and verified-payload count. A blocked preflight does not establish payload integrity. --all-checks continues independent checks after recorded blockers, while corrupt payloads remain unusable. Repeated input options support multiple activities.

The audit also writes original_definition_coverage.json and .md in the same output directory. These answer the review-readiness question: does every active activity transform rule have all its original definitions in llvm/full/module.ll? The audit enumerates full-module selector matches, including overloads, resolves aliases to their definitions, and checks exact P3/P5 input matches against the full module. A declaration is not a definition; a definition generated by a P5 rewrite is not an original implementation. A selector without any exact match is reported separately because its missing exact-function count is not known.

The first table groups missing original functions and globals across activities, with exact LLVM symbols, configured rule kinds, shared reviewStatus values, and the concrete missing-definition status. The second lists rules whose original definitions are available but whose model or technical review needs work. Rule counts, distinct exact-symbol counts, and activity/rule/symbol occurrences are separate units. Availability permits review to start; relevant callees, ABI details, effects and sink/lifecycle arguments may still need additional evidence. Neither a pending reviewStatus nor an automatic LLVM UNKNOWN determination establishes missing implementation evidence. Passing mechanical checks does not establish complete original-definition coverage or correct model semantics.

compilation/native_symbol_providers.json:status=PARTIAL has a narrower meaning: some native artifact paths named by Bazel link/archive actions were absent or had an unsupported format when symbol-provider capture ran. Read unavailableArtifacts and unsupportedArtifacts for the exact paths and counts. This is independent of pipeline_status.json:completeness=PARTIAL and of ZIP payload integrity. A captured native provider records symbols, hashes and provenance; the separate compilation/libraries/library_evidence.json identifies embedded native and source snapshots. Neither inventory establishes which archive member the final linker selected. For a missing original definition, trace P1/P2 compiler inputs, the full-module compiled bitcode index and native provider records to distinguish a source-acquisition omission from an unavailable prebuilt library.

Prefer repairing the first blocker before reviewing dependent evidence. Request a broader partial review only when its independent findings are useful; a repair may invalidate later results.

Activity status tables

Begin an analysis review or status update with a compact Markdown table for each activity. For a comparison, use activities as columns and put the count and severity in each cell. Keep the same checks and units in both views. Include the activity path, evidence/invocation identity, STIG producer version, and available stages so an archived result is distinguishable from an expected result after a local patch.

Kotlin owns the deterministic counts, severity, and initial Markdown rendering from structured review evidence and problem records. It prefills one review document with configuration tables followed by the two all-sink tables defined in Stage 4. Each activity document starts with a compact vertical summary: activity name, logical sinks in each table, active activity transform rules, P5 final-module body-validation matches / configured final-body checks, missing required P5 definitions, and captured CRITICAL and HIGH problem groups. These values reuse the detailed lists of affected items and problem counts; missing evidence remains UNAVAILABLE. The AI progressively fills the review observations, comparison cells, evidence notes, and next actions in a working copy outside the immutable archive. It must not change captured producer facts or confer transform review by editing the document. Distinguish emitted problem counts from newly assessed affected items and reviewer comparison statuses.

Both modes of stigCheckAnalysis, with or without --zip, write these activity outputs:

build/stig/stigCheckAnalysis/analysis_alignment_input.json build/stig/stigCheckAnalysis/analysis_review.template.md

The typed input uses schema ai.exida.stig/analysis-alignment-input version 2. It joins transform review facts, problem groups, lists of exact affected items, logical sinks, stage observations, and evidence hashes without changing the captured producer verdicts. ZIPs include review/analysis_alignment_input.json and review/analysis_review.template.md. Root stigCheckAnalysis renders the activity comparison from those same typed inputs. Partial collection uses only artifacts established as current by the collector and leaves missing stages UNAVAILABLE; it does not reinterpret excluded or retained files as fresh results.

stigCheckAnalysis writes no editable review into docs. The Markdown in task outputs and the ZIP is a generated template. Create a working copy later, when local or transferred evidence is actually reviewed. A dated directory can preserve independent investigations; the copy can live at any chosen location outside the input evidence and generated-output directory.

For retained ZIPs, generate the same tables directly without rerunning product analysis:

./gradlew :stigGenerateArchivedAnalysisReview \ --evidence-zip=/path/to/activity-one.zip \ --evidence-zip=/path/to/activity-two.zip \ --working-review-directory=docs/analysis-reviews/2026-09-10 \ --console=plain --info

The same task accepts --evidence-directory for extracted archives and --evidence-index for an existing local review_evidence_index.json. Each option can be repeated. Encrypted ZIPs use --password. ZIP member paths and duplicates are validated before extraction under task-owned _archives/<SHA-256>/ directories.

The standalone task verifies every manifest-listed payload's path, size, and SHA-256 before using it. Its default output is build/stig/stigGenerateArchivedAnalysisReview/, with per-activity subdirectories and a combined analysis_review.template.md; --output-directory can select another generated-output directory outside the archives. An optional --working-review-directory creates or refreshes <destination>/<Gradle project path>/analysis_review.md, translating colons to directories and preserving review cells. Without that option it produces build outputs only. For local analysis, supply the existing build/stig/stigCheckAnalysis/review_evidence_index.json with --evidence-index; a ZIP is unnecessary. The task has no native/P3/P5/P6/HTML producer dependency and does not modify the archives or validate changes made after their capture. Missing preoptimization application evidence in an old ZIP remains unavailable; the final-body count difference cannot be relabeled as proven optimization.

Both collection modes and the standalone task produce review/original_transform_evidence.json and .md, plus llvm/index-fullLlvm.json, llvm/index-p3.json, llvm/index-p5PreTransform.json and llvm/index-p5Final.json when the corresponding modules are present. Each index records exact symbol states, byte/line ranges and hashes, attributes, ABI parameters and sret positions, direct calls/callers, referenced globals, and bounded write/call excerpts. Bodies stay in the module. The review joins active selectors against the complete original inventory, including overloads absent from P3/P5. The local original_transform_evidence.md uses absolute module links; the review/ copy has portable archive links. Transform justification and confirmation belong to the shared registry rule; sink assessment cells remain in the persistent review worksheet.

stigPrepareTransformReviewEvidence produces review/transform_review_context.json, shared by configuration review and P6. It records distinct P3/P5 input matches, original compilation units, and original symbol/alias definition coverage without review hashes. stigCollectNativeSymbolProviders refreshes available Bazel link/archive artifacts independently of P1 cache reuse; compilation/native_symbol_providers.json records selected symbols, concrete artifact hashes, candidate roles, and unavailable/unsupported artifacts. A candidate archive definition does not prove which member the linker selected or its behavior. Missing native evidence in an older ZIP remains unavailable.

Current archive manifests include the producer's Git revision, dirty state and source fingerprint. A SNAPSHOT version alone cannot distinguish different builds. An older workflowContract.skill="check-analysis" label is informational; supported schema contracts and available evidence determine readability. That label alone does not call for gradlew clean.

The project registry is a catalog from which each activity selects its own rules. A rule defined in the project but not selected by an activity is normal and generates no warning for that activity. Neither that set difference nor a configuration candidate establishes a missing use(...) entry. Report one only when evidence identifies an unmet requirement of this activity and the existing rule is a justified way to satisfy it. An unused UNKNOWN registry rule likewise does not make the activity's selected configuration incomplete.

The table must cover these checks in order. Always show a count's unit; split functions and globals where both occur. Use separate rows for different severities, and link the full list of affected items behind each nonzero count.

Stage / check

Counted unit

Interpretation

Project registry: missing required model

Exact functions/globals with an established modeling requirement and no matching registry definition

Configuration problem only after necessity is established; a new rule can cover several affected items

Project registry: selected UNKNOWN models

Active rule identities and, separately, affected exact symbols

Concrete models are missing; inactive catalog entries are not activity problems

Project registry: review

Shared rule definitions

One reviewStatus per shared rule

Activity: configured uses and resolved active rules

Authored use(...) entries and resolved rule identities, separately if different

Inventory; do not silently drop stale or duplicate selectors

Activity: demonstrated missing required uses

Required use(...) edits and, separately, affected exact symbols

Name the unmet activity requirement; unselected registry entries alone produce no warning

Activity: rules awaiting shared review

Active rule identities

NEW emits HIGH; MODIFIED emits MODERATE; one incomplete-review problem per rule

Activity: stale or demonstrated unnecessary uses

use(...) selectors

Report the evidence; later optimization alone does not show that the entry can be removed

P3: declarations at the selected boundary

Exact functions/globals, distinguishing declarations, absent symbols, and resolved aliases

INFO inventory; P3 need not contain every transitive callee definition

Original code: missing evidence required for a selected rule's review

Active rule identities whose complete initial definition or sufficient effect contract is unavailable

Review is unestablished; P3 absence alone cannot establish original absence

P5: missing required definitions in the final module

Referenced application functions/globals outside the audited external-symbol allowlist

HIGH; provisional execution can continue, while final acceptance requires resolving the gaps

P5: recorded rewrite applications before optimization

Rule identities, exact rewritten definitions, and alias symbols separately

Application inventory; final surviving definitions are a different checkpoint

P5: missing or inconsistent expected applications

Exact affected symbols, with the associated rules

Contradiction only when current evidence establishes a required application that is unaccounted for

P5: rules with final definition matches and body-shape violations

Matched rules; separate exact-symbol violation count

A selector match alone does not establish a valid body

P5: verified removals after rewriting and optimization

Rules with all matches removed; separate exact-symbol count

INFO; retain application proof and final-state evidence

P5: unexplained accounting differences

Affected rule/symbol identities in their respective columns

Contradiction; do not label the arithmetic difference as an optimization count

Ordinary incomplete configuration is HIGH; a changed rule awaiting renewed review is MODERATE; contradictory or unusable tool evidence is CRITICAL. Verified optimization removals and diagnostic inventories are INFO observations, not failing problems. Preserve a producer's recorded severity and label any proposed reassessment explicitly. A verified zero has no failing severity; N/A means the check does not apply, and unavailable means required evidence is absent. Never turn an unexecuted stage, an excluded artifact, or an unproven optimization outcome into zero.

Count twenty missing functions as twenty symbol problems and thirty-four as thirty-four. Review/review still counts each rule once even when it matches several symbols. If evidence establishes that two required use(...) entries leave six functions unhandled, show two edits and six affected functions. Mere candidate counts do not meet this condition. Deduplicate the same obligation across stages using its canonical identity; do not sum overlapping rows or INFO observations into a problem total. An older producer's one aggregate contradiction must not be presented as twenty emitted canonical records.

The generated review calls these counts problem groups. One group contains records with the same activity (projectPath), category, check (problemId), and affected item (subjectId). Repeated reports of that group count once, including reports from different producing tasks. Its severity is the highest recorded severity, and the expanded details retain every distinct captured message, detail, and evidence value.

For example, a P3/P5 inventory disagreement affecting two exact functions produces two groups even if one checker bug causes both. Pending review and missing P5 validation reported together for one transform rule produce one group. An affected item can also be a sink or task: several annotation warnings reported against one inventory task can share one group. Consequently the count describes reported groups, not the number of independent root causes, signals, or individual messages. The expanded problem rows show the affected item, recorded disagreement, exact LLVM symbols where available, and evidence links. An inventory entry that is absent does not by itself establish a missing LLVM definition.

The evidence links must identify the exact producing task, DSL location, and manifest-mapped payload. Use review/transform_review.json and the configuration proposal for registry/use and review facts, llvm/full/module.ll for original definitions, llvm/p3/module.ll for selected provenance, llvm/p5/bitcode_rewrites.json for the producer's recorded application checkpoint, and llvm/p5/bitcode_transform_validation.json plus llvm/p5/unresolved_application_symbols.json for final P5 checks. The local P5 files belong to stigAnalysisP5ProduceBitcodeTransformEvidence; the public validation gate is stigAnalysisP5ApplyBitcodeTransforms. The root review task combines activity results without reclassifying them. Follow the table with each activity's earliest unresolved gate, blockers, and next action. Configuration-only tables cannot establish downstream sink alignment.

Stage 1 — complete transform configuration

Start separately for every activity. Establish archive identity and stage availability first. If stage evidence is contradictory, identify the producing layer before relying on it for a repair or review. Available, independent LLVM facts can still be reviewed; the activity cannot advance on contradictory evidence.

Investigate missing or incorrect configuration in the project's or activity's build.gradle.kts. Use precise names:

Configuration finding

Authored location / evidence

Demonstrated missing required shared transform rule

Project stigProject { bitcodeTransformRegistry { ... } }

Demonstrated missing required activity use(...) entry

Activity analyzerInput { bitcodeTransforms += { use(...) } }

Incorrect rule semantics, selector, owner or required compilation input

The corresponding shared rule or activity configuration, justified by original LLVM and compilation evidence

Transform application/validation failure or contradictory evidence

P5 and configuration diagnostic artifacts; investigate the responsible configuration or producing tool

Pending or stale review

The shared registry rule's reviewStatus; review in Stage 2 once configuration validation is sound

A referenced symbol without a definition in final P5 is a configuration-investigation finding. Inspect unresolved_application_symbols.json, the shared registry, the activity's active rules and the selected compilation inputs to determine which configuration part is missing or incorrect. Check for an existing shared rule before adding another. Candidate counts, configured-rule counts and unresolved LLVM-symbol counts remain separate units.

Establish necessity before calling a rule or use(...) entry missing. For example, a referenced application symbol that survives in final P5 without a definition identifies an unmet requirement; choosing between a compiled implementation and a justified model is a separate decision. A rule merely available in the registry, a native inventory symbol, or a declaration in P3 does not establish that requirement. Keep optional candidates as navigation facts without an activity warning. If an older producer emitted HIGH for those facts alone, report its recorded output and correct the classification in the producer; do not manufacture new missing-use problems in the renderer.

P3 is a selected provenance/reference module for reviewing the transformations. It is not required to include the whole transitive implementation closure. For example, P3 may contain the body of foo() and a call to a declared bar(). If a justified P5 model of foo() no longer calls bar(), bar() need not have a body in P3 or survive in final P5. This is an intentional finite boundary, not automatically a configuration gap. Retain the original call and the replacement in the review evidence. If bar()'s effects matter to justifying the replacement, use sufficient compiled evidence or an effect contract; otherwise leave that semantic comparison unestablished. Do not recursively add every callee, infer a NOP from a declaration, or claim equivalence without the relevant effect evidence. An unconfirmed selected foo() rule retains its own review obligation; it does not create a missing bar() use.

P3 and P5 have different purposes and selected inputs. A symbol's absence from P3 alone does not prove it is unnecessary in P5, which can contain generated harness functions and supplied implementations. Check each stage's declared requirements and the actual final references.

stigDeriveAnalysisConfiguration resolves each active activity transform rule against the actual P3 bitcode's readable representation, stigAnalysisP3BuildProvenanceBitcode/module.ll. Its reported P3 matches include matching overloads, declarations, and function aliases. The same task separately resolves p5InputMatchedSymbols against stigAnalysisP5BuildUntransformedAnalyzerInput/module.ll, archived as llvm/p5-pre-transform/module.ll. P5 application comparisons use that input match list: P3 can contain overloads excluded by P5 source selection, and P5 can contain functions introduced by the harness. Exact P5 applications are compared directly with input matches after resolving recorded aliases. The proposal records sourceInclusionTriggers separately: those exact symbols explain why an implementation source file was included. Compiling that source file can supply more matching functions than the triggers name.

For example, one unresolved overload can cause time_utils.cpp to be included, while compiling that file supplies both overload definitions. If review/transform_review.json lists one P3 match but llvm/p3/module.ll contains two matching functions and llvm/p5/bitcode_rewrites.json records both applications, the reported P3 match list is wrong. It does not establish a missing definition in final P5 bitcode. Repair the P3 match producer and regenerate with stigCheckAnalysis --configuration-only --zip; retain the separate final-P5 required-definition check. Corrected match sets can change the assumptions of the shared rule and require renewed engineering review.

Transform rule is the umbrella term. Name the actual DSL operation, for example rewriteFunctionWithTransfer, rewriteFunctionWithTransfers, rewriteFunctionToNop, rewriteFunctionToNoReturn, or rewriteFunctionWithImplementation. A NOP or no-return rule is not a transfer-function definition.

For each missing or incorrect rule, inspect its original LLVM definition and relevant callers. Resolve the exact symbols, parameter/receiver/return mappings, memory effects, and return or termination behavior. When repair is requested, add the justified project registry rule definition in stigProject { bitcodeTransformRegistry { ... } } and select it with an activity transform-rule use(...) entry in analyzerInput { bitcodeTransforms ... }. The project Gradle build script normally owns the project registry; the activity Gradle build script owns its use(...) entries and reviews. A real implementation compilation unit selected by configuration or a custom replacement may be required when a transfer cannot preserve the behavior. See Bitcode rewrite modeling.

An unresolved LLVM symbol does not automatically require a transfer rule. Do not insert NOP/UNKNOWN rules, widen softwareUnderAnalysis, or classify a function as runtime infrastructure just to clear the check. An exploratory UNKNOWN rule remains incomplete. Audited symbols in allowed_external_symbols.json are distinct from missing configuration for application symbols; the completion condition is not that every LLVM declaration has a body.

Zero missing required final definitions is required for complete P5 evidence, rather than for provisional execution. Transform accounting is an additional check: every expected exact application must be accounted for at the rewrite checkpoint, and every surviving required definition must satisfy its applicable validation. A successful rewrite can subsequently lose its last use and be removed by optimization. Calls present before other rewrites do not establish calls in the final module.

With current producer evidence, bitcode_rewrites.json records applications before post-rewrite optimization, while bitcode_transform_validation.json examines the final module. The activity review's p5BodyRuleAccounting separates rules with surviving rewritten definitions from ELIMINATED_AFTER_P5_OPTIMIZATION. Their sum must equal the number of P5 input matched transform rules in the final-body-check subset: NOP, no-return, and transfer rewrites. The p5InputMatchedFinalBodyRuleCount and accountedP5InputMatchedFinalBodyRuleCount fields record that comparison. A P3 match absent from P5 input is not an application removed by optimization; a rule with no input matches records NOT_IN_P5_INPUT. That subset excludes other active rule kinds. See Bitcode rewrite modeling for the precise fields and checkpoints. Exact LLVM aliases can resolve several selected symbols to one definition; require the recorded alias mapping rather than inferring it from constructor names. For a rule with several matches, account for every symbol even if another match survives.

An unmatched final-body check is not automatically an INFO removal. Require complete valid application evidence and an accounted final state; a remaining required undefined reference or body-shape violation still fails. Older ZIPs whose rewrite report was produced only after optimization cannot establish the removed applications. A local code fix and a count difference cannot retroactively fill that gap; report the older diagnostics and expected rerun result separately. Optimization status also does not confer semantic review or remove an active rule's review duty.

A declared noreturn attribute establishes the no-normal-return contract. A nounwind attribute or a zero-parameter signature does not establish absent memory effects or justify a NOP. If the original body and sufficient alternative effect evidence are absent, identify the missing implementation evidence rather than inventing a transfer.

After adding or changing semantic rules, obtain fresh P5 and configuration evidence before advancing:

./gradlew :activities:my_activity:stigCheckAnalysis --configuration-only --zip --console=plain --info

Run this in the generating checkout when sources or other native inputs are required. For remote evidence, provide the exact configuration patch and command to the user, ask them to transfer/push the changes to the real repository and rerun there, then review the new ZIP. A review request does not itself authorize a Git push.

Stage 2 — review every active rule

Once the required transform configuration is present and its validation is sound, review every active activity transform rule, including rules absent from actionItems. transformReviews lists these rules. A rule and its exact matched LLVM symbols are separate counting units.

For each active activity transform rule establish:

  • the final shared registry model and its rationale, with generated LLVM observations kept separate;

  • behavior of every original exact match and relevant callers/callees in the complete initial llvm/full/module.ll;

  • return values, hidden sret buffers, constant initialization, globals and writes, and their relation to configured sinks/lifecycle;

  • ownership evidence from transform-owner provenance compilation units and any ABI/overload differences;

  • resolution of semantic conflicts and successful current P5 application/body validation;

  • the shared project registry rule's reviewStatus.

A name-wide rule must be sound for every exact match. Split by mangledSymbol when those functions require different semantics. P5 replacement code cannot prove that its transform rule matches the original. An LLVM CONFLICT observation means established overload summaries disagree. Ownership differences or a known summary alongside UNKNOWN do not establish a conflict. A concrete common model still needs review against every original variant.

The single authored review status belongs to each shared project registry rule in the root build.gradle.kts: NEW, MODIFIED, or CONFIRMED. Activity use(...) entries only select rules. A newly created rule defaults to NEW; an automatic edit to an existing rule sets MODIFIED; unchanged regeneration preserves the status. For manual model or C/C++ edits, set MODIFIED in the same change. There are no review fingerprints or source-body checksum manifests. Changes to originals and activity assumptions require explicit review; Git history provides the change record.

A used NEW rule emits a HIGH warning; a used MODIFIED rule emits a MODERATE warning. These findings obey the normal failAt policy. CONFIRMED removes only the pending-review warning: incomplete models, missing evidence, and failed P5 application/validation are still checked. An UNKNOWN rule kind cannot be confirmed.

llvmDerivedBehavior remains the generated LLVM determination of original behavior. Read it without editing it, even when it is UNKNOWN. Record the justification for the selected model in the registry's reason and record the completed review as CONFIRMED. Historical confirmation metadata in older archives remains captured history; it does not establish the current status. The first sufficient activity review can confirm a shared rule. Record its activity scope and evidence alongside the rationale; other activities can reuse the conclusion subject to the compatibility checks described in Bitcode rewrite modeling.

After completing the semantic review, use the root task to record confirmation:

./gradlew :stigConfirmFunctionRewriteRules --function='app::IsFinite' --preview --console=plain --info ./gradlew :stigConfirmFunctionRewriteRules --function='app::IsFinite' --console=plain --info # When a fresh evidence capture of the new status is needed: ./gradlew :stigCheckAnalysis --modules=:activities:example --configuration-only --console=plain --info

Repeat --function for additional exact registry identities; an exact-overload identity includes [llvm=<symbol>]. --modules filters to rules used by the selected activities, while confirmation still edits only the shared root declaration. Omitting both options selects every project registry rule, including unused ones. --preview writes a candidate root build file without updating authored configuration.

The command records the caller's completed review. It does not run native compilation, P3/P5, or an equivalence test. Before any edit, it checks that all selected models are concrete and each has exactly one literal registry declaration. Computed declarations require an explicit edit. It is never an automatic dependency of analysis.

build/stig/stigConfirmFunctionRewriteRules/function_rewrite_confirmation.json records the selected rules and old/new statuses. The proposed root file is candidates/build.gradle.kts in the same directory. These are build outputs; the root DSL is the persistent review record. transform_review.json retains original symbol states, generated LLVM observations and P5 evidence without review hashes. Reread the saved root status after a metadata edit; it does not change LLVM semantics or require another native/P5 run. To publish updated captured statuses, collect evidence in a new Gradle invocation because the recording invocation already loaded the previous configuration. An existing archive retains its historical statuses until a new capture is produced.

Advance when every active rule is CONFIRMED, has a concrete model and successful P5 validation, and has no remaining configuration or transform-review findings requiring action.

Configuration review summary

At the end of configuration audit/alignment, show the results for Rules used by <exact activity Gradle path>. List the selected rule identities and actual DSL operations, summarize counts by operation and review status, and include totals and the unresolved count. These counts include only the active rules selected by that activity's use(...) entries. Other project registry rules are outside this summary and do not prevent the activity's review from completing. Keep rule counts separate from exact LLVM symbols and P5 applications.

Then show two tables, each with one row for every configured logical sink:

Expected propagation — data/control flow (data-and-control-flow)

Sink

ASIL

Full LLVM

P3 LLVM

P5 LLVM

Adjacent-stage agreement and evidence

<logical sink>

<ASIL>

UNASSESSED

UNASSESSED

UNASSESSED

UNASSESSED

Cascading propagation — cascading faults (cascading-faults)

Sink

ASIL

Full LLVM

P3 LLVM

P5 LLVM

Adjacent-stage agreement and evidence

<logical sink>

<ASIL>

UNASSESSED

UNASSESSED

UNASSESSED

UNASSESSED

These rows illustrate the layout, not results. Use the same logical-sink inventory in both tables, including healthy, negative, unreached and uncalled sinks. Expected propagation uses sources at the sink's ASIL or higher; cascading faults use sources below its ASIL. Include the contributing sources, not just a FLOW/NO_FLOW label. A known empty source partition is N/A with a reason. An absent inventory or module is UNAVAILABLE; an available module with no completed trace is UNASSESSED; an assessment invalidated by a model change is STALE.

Full LLVM means llvm/full/module.ll, P3 means llvm/p3/module.ll, and P5 means final llvm/p5/module.ll. Check the full-to-P3 and P3-to-P5 transitions under the recorded source partitions, lifecycle and modeling assumptions. P3 is selected provenance: an omitted function or absent harness marker is not a NO_FLOW observation. Use the original interface mapping and explain selection or model differences with evidence.

These are the LLVM columns of the two Stage 4 worksheets. Complete the existing working tables rather than creating a second independently maintained assessment. The compact view above can summarize those same cells; retain separate P3-vs-full and P5-vs-P3 assessments in the working review. Link the actual tables when reporting them in a document. Do not defer these LLVM comparisons until after analyzer execution. Configuration alignment is complete only when every applicable LLVM comparison is assessed and justified; confirmed rule statuses or empty gap lists alone do not establish that result.

Handoff to full analysis

After the configuration checks, current transform review, P5 validation and both LLVM sink tables pass, propose the next action in plain language. For example:

This is a scoped analysis-model conclusion. It does not assert identical instructions, numerical behavior or whole-program binary equivalence, and it does not establish analyzer or report correctness. If a required comparison or P5 check remains incomplete, report that pending work instead of presenting this success message.

If source files changed, identify the consumer and changed STIG/PhASAR repositories and recommend preserving those changes in commits before handoff. Commit and push only when explicitly requested. For execution on another machine, transfer the committed and pushed changes using the consumer's recorded synchronization workflow, including changed local sibling overrides. Use its existing git subrepo pull paths for imported repositories and ordinary Git for standalone checkouts. A consumer update alone does not update a local STIG or PhASAR override.

Propose the exact command from that consumer's root, substituting its activity path and a fresh evidence destination. The full task path comes before its options; omit --configuration-only. A generic example is:

set -o pipefail ./gradlew :activities:example:stigCheckAnalysis \ --zip --zip-directory=../analysis-evidence/example/full-reviewed \ --console=plain --info 2>&1 | tee /tmp/stig-example-full-analysis.log

The task runs or validly reuses its analyzer and report prerequisites and collects the available evidence. It prints the actual ZIP paths and a prompt for reviewing analyzer/report alignment. A partial or failed producer chain still needs its first unresolved stage diagnosed; creation of the ZIP is not proof of successful analysis.

Suggest a fresh Codex thread for the full-evidence review when that makes the handoff clearer; it is optional. Supply the saved configuration review, accepted assumptions, source revisions and the newly printed ZIP paths or indexes. The next review reuses still-current configuration conclusions and extends both sink tables through the selected P6 module, analyzer JSON, P7 and actual HTML. A different computer may run the source-backed pipeline while the portable ZIP is reviewed here. Do not launch this next phase merely because the command has been proposed.

Stage 3 — choose a supported rerun

The current replay boundary matters when the review machine has no product sources:

Change / operation

Current source-free support

Inspect compiled functions and callers

Supported from the captured LLVM checkpoints when sufficient definitions/effects are present

Change only review metadata

No semantic LLVM rebuild is intrinsically needed; validate the new registry status in the generating checkout or with its valid Gradle inputs

Rebuild P3 or construct P5 from llvm/full/module.ll

No portable archive task currently implements this. Normal P3 and P5 construction compile selected sources and link their outputs

Reapply only post-link transfer/NOP/no-return logic

The rewrite engine operates on LLVM and uses pinned LLVM tools, but the normal P5 task also depends on P3 per-unit bitcode, compiler inputs, and validation evidence. There is no supported archive-only P5 replay entry point

Change real units, harness, pre-link replacement sources, or custom native models

Requires the corresponding compilation inputs; the earliest linked LLVM module alone is insufficient

Run retained transformed inputs, including a configuration checkpoint with no previous P6 result

Supported by stigAnalysisP6RunAnalyzer --start-with=transformed with the captured bitcode, run plan, configurations and sidecars; see the transformed-input workflow

Reexecute a captured P6 run with targeted fact diagnostics

Supported by stigReplayArchivedAnalyzerRun, with the exact selected module and required captured run evidence

Regenerate P7 and HTML from a replay result

No portable report-replay task currently accepts that result; use the generating checkout and rerun the affected producers and report

Do not copy archived modules into ordinary task output directories, exclude their dependencies, or substitute local consumer stubs. Gradle cache reuse is different from replaying an archive. A future portable transform or report replay must preserve the same producer checks and evidence identities; it is not an available command today.

Choose the next validation from what changed, and retain the last validated evidence for comparison:

Edited input or producing layer

Review and evidence that must be renewed

Shared transform logic or an activity's active rule selection

Configuration/P5 validation and current transform review for every affected activity, then its downstream sink comparisons

Review metadata only

A new configuration check of the persisted project registry status; no intrinsic LLVM semantic change. Let Gradle determine which producer outputs it can reuse

Product compilation inputs, source selection, harness, or compiled replacements

The affected compilation/construction stage, current transform review, and every dependent stage; use the generating checkout when required inputs are absent locally

Analyzer or slicing behavior

The affected P6 input/run and every dependent P7/report result; compare against the same recorded source partition and analysis settings

P7 aggregation or report generation

The changed producer and its dependent report/HTML outputs, checked against the established upstream sink observations

Accepted knownGaps declarations

The activity's assessment and report chain, including the comparison of observed and declared gap sets in both directions

A new archive does not inherit a completed review solely because the activity name is unchanged. Match its rule, module, run-plan, and configuration identities to the reviewed evidence and revisit every affected comparison.

Stage 4 — align every sink through adjacent stages

Kotlin must prefill the sink worksheets after the configuration tables, even while some stages are unavailable. For each activity produce one data-flow table (data-and-control-flow) and one cascading-fault table (cascading-faults). Include every configured logical sink in both, including healthy, negative, unreached, and uncalled sinks. ASIL can be a column or a separate table group. Reconcile the interface inventory, complete run plans, analyzer records, and report tables; flow_gaps.json contains only problematic rows and cannot define table coverage.

During configuration review, complete the full LLVM/P3/P5 comparisons as described in Configuration review summary. After those checks pass, collect full evidence with stigCheckAnalysis --zip and extend the same comparisons through the analyzer and report. A configuration-only archive must still show the known sinks, with unavailable analyzer/final cells; an absent sink inventory must be reported as unavailable rather than an empty successful table.

When downstream evidence is already available during Stages 1–2, a preliminary review may list sink differences and the first differing adjacent stage. Mark these observations provisional. Resolve configuration and current transform review first; defer downstream repairs and final alignment conclusions until those gates pass. A contradiction in the configuration evidence itself must still be investigated in Stage 1.

The comparison identity is activity + analysis kind + sink ASIL + logical sinkKey, mapped to exact LLVM endpoint symbols and physical analyzer sink records. STIG normally has at most two aggregate analyzer results per activity per sink ASIL, not two per activity and not two per sink:

Analysis kind / run identifier (runStem)

Selected sources

Report gap condition

data-and-control-flow-<ASIL>

Sources at the sink's ASIL or higher

No expected source-to-sink flow

cascading-faults-<ASIL>

Sources below the sink's ASIL

Lower-integrity source-to-sink flow is present

The plan omits a pass with an empty source set. Record the reason and whether the intended safety question is covered; an absent pass is neither an executed negative result nor a successful missing-flow check. Resolve a required but uncovered analysis scope before completion.

For each sink and applicable run, compare the same source partition, lifecycle, data/control dependency semantics, solver, alias mode, and feasibility policy at every adjacent checkpoint:

initial LLVM module → P3 bitcode → P5 input → final P5 bitcode → selected P6 module (including any slice) → analyzer JSON → P7 logical-sink/diagram data → report table JSON → final HTML report

The arrows order the comparison. P3 and P5 are constructed from their selected compilation inputs.

For the LLVM checkpoints, trace the relevant compiled operations and callers. Generated harness marker names may not exist in the initial LLVM module: use the captured interface/harness mapping to the corresponding original payload operations. A missing marker or an incomplete trace means unestablished, not unreached. Negative claims need sufficient coverage of the relevant call/data-flow closure.

In each matrix cell record the flow verdict, contributing sources, exact evidence location, and whether the conclusion is established, unavailable, or inapplicable. Keep taint reachability separate from call reachability and runtime feasibility. sink.leaked is the structural solver verdict; an ICFG call alone does not prove taint. Aggregate the covered physical sink records according to the analyzer/P7 contract, and preserve source/fact provenance. A field-insensitive alias result may over-approximate runtime behavior; optional feasible paths do not redefine the structural verdict. See Source-code analysis diagrams.

Worksheet columns and cell ownership

Use this column order for each of the two tables. The sink and ASIL identify the row; the following nine columns are the requested stage observations and adjacent-stage assessments:

Sink

ASIL

Initial LLVM

P3

P3 vs initial

P5

P5 vs P3

Analyzer

Analyzer vs P5

Final HTML

Final vs analyzer

<logical sink>

<ASIL>

UNASSESSED

UNASSESSED

UNASSESSED

UNASSESSED

UNASSESSED

UNAVAILABLE

UNAVAILABLE

UNAVAILABLE

UNAVAILABLE

The example is a worksheet layout, not an analysis result. Initial LLVM means the initial LLVM module (llvm/full/module.ll), currently produced from P2 LLVM compilation; it is not native GCC machine code. P5 means final P5 bitcode. The Analyzer comparison must also name and check the selected P6 module and any slice. Keep intermediate evidence links for post-rewrite/pre-optimization P5 and P7 in the relevant comparison notes; the nine displayed columns must not hide those transitions.

Stage cells contain observations such as FLOW or NO_FLOW, with contributing sources and evidence links. Use UNREACHED/UNCALLED only when the corresponding evidence establishes that state; absence of a record or marker does not. In the data-flow table, FLOW refers to the selected equal-or-higher-ASIL sources. In the cascading-fault table it refers to the selected lower-ASIL sources. A flow observation is separate from whether the pipeline represents it correctly: an undesirable cascading fault can have OK in every comparison column.

Kotlin fills identities, available producer observations, paths/hashes, canonical problem counts, and comparisons that a deterministic check actually establishes. It must not infer an original/P3/P5 flow verdict merely from a symbol being defined or called, or prefill semantic agreement from matching totals. A present module awaiting a trace is UNASSESSED. Missing stage evidence is UNAVAILABLE. No applicable source partition is N/A with its recorded reason. LLVM traces established later by the AI are explicitly reviewer observations with supporting references.

Comparison status

Meaning / required support

OK

The current evidence and relevant analysis/model contract support this transition; record who/what checked it and the proof

ERROR

A demonstrated disagreement for this sink; name the earliest differing producer and evidence

UNASSESSED

Inputs exist but the comparison or relevant effect justification is incomplete

UNAVAILABLE

A required input or stage observation is missing

STALE

A previous assessment refers to superseded modules, configuration, run settings, or outputs

N/A

This comparison does not apply, with an explicit reason

These are review statuses, not another ProblemSeverity enum. ERROR does not itself mean every such cell is a new CRITICAL problem; canonical problems retain their own identities and severities. OK for P5 vs P3 means a justified application of the selected analysis models, with the relevant dependencies accounted for. It does not require identical instruction/call inventories: an intentional foo() rewrite may remove its call to bar(). A changed flow needs an explanation under the model contract; it must not be silently accepted because the rewrite was configured.

Progressive review and fresh evidence

The generated/archive template remains immutable. At review time, the standalone review task can initialize a persistent Markdown working copy outside the ZIP and disposable task outputs; the AI fills its designated review cells and notes. Preserve generated stage facts as evidence quotations. The working copy may add an LLVM trace or change an assessed comparison, but may not edit a captured analyzer verdict to make it agree. Refresh such a verdict from a new, identified producer result.

Each generated review cell has an HTML comment marker containing its stable identity, evidence fingerprint, and generated seed fingerprint. Identity covers the activity, analysis kind, sink ASIL, logical sink, and stage/transition. Keep these stig-review-cell markers intact when editing the visible assessment before them. Keep additional notes outside the stig-review:generated:start/stig-review:generated:end region; text elsewhere inside that region is regenerated from producer facts.

Fingerprints bind assessments to the relevant module, configuration, selected source/run contract, and results. Kotlin preserves an edited cell when its evidence still matches. On changed evidence it retains the old assessment with STALE; assessments for removed sinks are retained in history. Notes outside the generated region survive every refresh. An existing working file without a valid generated region is rejected rather than overwritten. Independent activities keep their assessments; an unchanged sink name alone never carries an old OK into new evidence.

The prefill deliberately leaves semantic LLVM traces and positive source-contributor equivalence UNASSESSED. It can check exact byte identity, physical configured-sink coverage, conflicting HTML rows, and captured boolean disagreement. Matching positive booleans do not establish contributor agreement. Every inventoried sink remains in both tables, including QM, healthy, negative, and uncalled sinks; an empty known source partition is N/A, with its reason. Counts come from captured evidence, not from the review cells.

After a bug fix and verified rerun, the AI can change Analyzer vs P5 from ERROR to OK, citing the new analyzer result and its exact selected LLVM inputs. Keep any unregenerated final result identified as the older output and set Final vs analyzer to STALE or UNAVAILABLE. If a fresh final output still disagrees, that comparison is ERROR; after fresh HTML and source-contributor checks agree, it can become OK. A code edit or a successful unit test alone does not update a captured activity result.

Final means the actual generated activity HTML. tabulator_tables.json currently captures report/diagrams.md input; label that evidence as report input and leave the final-HTML cell unavailable if HTML was not captured/checked. Do not set the final comparison to OK by comparing two copies of the same report-input JSON. Worksheet OK is a review assessment; transform reviewStatus is recorded in the shared project registry, while knownGaps still requires the separate user decision.

Locate the first differing adjacent pair, rather than comparing only the initial LLVM module with the final table:

First disagreement

Producing layer to investigate

Initial LLVM module → P3 bitcode

Provenance selection, compilation, ownership, or mapping to original operations

P3 → linked/final P5

softwareUnderAnalysis, harness, replacement compilation, transfer semantics/application, or optimization

Final P5 → exact P6 module

Slicing and run-plan/module selection

Exact P6 input → analyzer JSON

Analyzer configuration, solver, or native analyzer implementation

Analyzer JSON → P7 → report/HTML

Logical-sink aggregation, diagram transformation, table generation, or publication

For an authorized repair, fix that producer and rerun it and all invalidated downstream stages. An analyzer defect can be investigated and verified locally with the archived P6 replay below; that run does not regenerate P7 or HTML. Maintain the same input hashes and run semantics when assessing the fix. Require fresh downstream report evidence before calling the activity aligned. Neither matching gap counts nor matching two files derived from the same wrong producer proves agreement with the original compiled behavior.

Stage 5 — record accepted gaps and verify completion

Only after the stage results agree, discuss any remaining cascading faults and missing expected flows with the user. Record the accepted defective logical sink fields in that activity's build.gradle.kts:

stig { element { knownGaps { cascadingFault("Fusion.lane_width") missingExpectedFlow("Fusion.event_data_qualifier") } } }

Use the actual stable field from sinks[].field in the endpoint sidecar, not an LLVM symbol or diagram filename. knownGaps is the public DSL. knownCascadingFaults and knownMissingExpectedFlows are internal P7 task properties. Keep healthy sinks undeclared. Known gaps cannot excuse missing transform configuration, unconfirmed transforms, uncertain original behavior, or a toolchain discrepancy.

A current accepted gap is SOURCE_CODE/LOW. An undeclared observed gap is SOURCE_CODE/HIGH; stale, duplicate, wrong-kind, or unresolved declarations are CONFIGURATION/HIGH. Compare observed and declared sets in both directions. Then rerun the activity's stigCheckAnalysis --zip to regenerate/reuse its stigGenerateHtml chain and inspect its current canonical problems.jsonl outputs.

An activity is complete only when all of these hold:

  • every required stage has current, attributable evidence and the all-sink comparisons through generated HTML agree;

  • final P5 validation passes with zero referenced application symbols lacking definitions outside the audited runtime allowlist;

  • every active activity transform rule has shared reviewStatus = CONFIRMED and zero unresolved conflicts;

  • P6 analysis/provisional_analysis.json has no provisional boundaries and evidenceReady = true;

  • the observed cascading-fault and missing-expected-flow sets exactly match the accepted knownGaps declarations;

  • no unresolved HIGH/CRITICAL configuration, toolchain, or other applicable activity problems remain.

Track each activity's current stage, blockers, last validated evidence identity, and next command independently. One activity may be complete while another is waiting for missing transform configuration or user review. A shared registry change invalidates every affected use, not unrelated activities. A root stigListProblems --atLeast=HIGH is useful once a project-wide report is appropriate; it is not an activity-isolated completion gate because it schedules root HTML.

Collect a failing chain

./gradlew stigCheckAnalysis --configuration-only --zip --continue --console=plain --info ./gradlew stigCheckAnalysis --zip --continue --console=plain --info

Choose the required mode. Each started activity retains available evidence after a failure by default; --accept-partial-results explicitly selects this default. Gradle's --continue separately lets other independent activities finish after actual task failures. It is unnecessary for HIGH findings below the configured failAt threshold, including missing referenced implementations and unreviewed rules. Setting failAt=HIGH deliberately makes those findings fail tasks. Neither behavior makes a failed analysis pass. Without --zip, collection retains local metadata and the review template. The final collector records upstream and recoverable collection errors in the archive without failing merely because those errors exist. An inability to write the requested output still fails collection. If producer evidence cannot be parsed into review tables, the ZIP retains that raw evidence and a Markdown notice that review generation is unavailable. pipeline_status.json records the rendering error; no typed review facts are invented for the failed rendering. Malformed activity summaries are also marked unavailable in the root summary.

Read pipeline_status.json and excluded_evidence.json for partial collection. Full-mode output also has pipeline status. A normal configuration archive uses its manifest pipeline status, review/diagnostic_status.json, and P5 status; it need not contain the partial-attempt metadata. COMPLETE describes collection of the requested mode, not semantic alignment. Configuration completeness never establishes that P6 ran. gapCount=null or absent downstream files cannot establish zero flow gaps.

Partial collection includes only current or Gradle-validated evidence. Retained files from unexecuted producers and unchanged files from failed producers are excluded, even if a failed task rewrote identical bytes. Failed P5 production can retain a final module and diagnostics while its stage status remains failed. Inspect the status, not file presence or the collector task's successful exit alone. The root export finalizer saves available current-invocation modules even after a producer fails and names unexecuted/unavailable selections in the collection manifest. A prior ZIP or old module output is never counted as a successful new collection.

The guarantee starts when the activity attempt marker runs. Build-configuration errors, a terminated Gradle process, or an archive-write failure can prevent collection. An older ZIP left on disk does not establish that a new attempt succeeded. Preserve these distinctions for every activity in a root invocation.

Replay a captured analyzer run

After extracting a suitable full-mode archive, choose an actual runStem from selected_p6_modules.json:

./gradlew stigReplayArchivedAnalyzerRun \ --evidence-directory=/absolute/path/to/extracted-evidence \ --run=cascading-faults-A \ --output-directory=/tmp/stig-replay-my-activity \ --console=plain --info

For a collection with several modules, also pass --module=:components:one using its exact captured Gradle path. Replay resolves the selected module's logical paths through the collection mappings, including shared bitcode.

The task validates manifest payloads, the exact selected .bc/.ll pair, the sliced run plan, configuration, and the captured analyzer JSON's execution settings. It preserves analysis semantics and remaps machine-local execution paths. It has no consumer P1–P7 dependency and does not compile product sources. The configured STIG/analyzer version and local STIG/PhASAR checkout policy still apply; record the actual analyzer identity used for a repair replay.

A partial full-mode archive is accepted by this replay task only when those required payloads exist, including the captured analyzer JSON used to verify settings. For a configuration checkpoint with no prior P6 result, use stigAnalysisP6RunAnalyzer --start-with=transformed. That mode requires captured executable bitcode and a complete run plan/configuration; a P5 module by itself or an older LLVM-text-only configuration archive is insufficient. Preserve the generating configuration rather than inventing an analyzer invocation.

Prefer targeted diagnostics by repeating --debug-facts-at-function=<exact-mangled-symbol> and optionally adding --debug-fact-filter=<literal-label>. Use --debug-trace only if targeted evidence is insufficient; it emits high-volume per-instruction output. Replay writes analysis-<runStem>.json, replay_run.json, the command, logs, and sink_summary.json outside the archive. These are new diagnostic results, not replacements for the captured evidence.

Archive protection and repository synchronization

Add --password with --zip to encrypt payloads using AES-256. Blank passwords and --password without --zip fail. STIG does not write the password to task-input metadata, logs, README, or manifest. ZIP entry names and compressed sizes remain visible. Without a password the archive is unencrypted and STIG prints a warning.

Local evidence remains under build/; ZIP export uses the exchange directory described above. Generation does not stage, commit, or push. The separate root option --sync-evidence-repositories explicitly invokes the consumer's scripts/git-subrepo-sync.sh; that script can pull, commit synchronization metadata, and push. Use it only when that synchronization outcome was requested.

Ask $stig:source-analysis

After configuration-only collection, stigCheckAnalysis ends its evidence report with:

The generated prompt starts with an empty line and names the actual evidence ZIPs or local evidence indexes, the current analysis log, and selected Gradle activities. The log path identifies STIG's captured invocation log; a shell-created tee log has a separate, caller-chosen path. If analysis log capture did not start, the prompt reports it unavailable instead of pointing to a previous invocation's file. The prompt identifies llvm/full/module.ll, resolved through the collection manifest, as the primary reference for original behavior. P3 and P5 establish selection and application; local replacement sources cannot establish what the original function did. It requests original-behavior review, a proposal for each function/global before edits, repair, and fresh P5 validation. It also requests selected-activity rule totals, both sink tables through full LLVM/P3/P5, and a full-analysis handoff after successful configuration alignment. Reviewers validate P5 behavior against Full LLVM and preserve the file-level softwareUnderAnalysis boundary. Simple field/receiver/parameter/return transfers are preferred; Kotlin helpers must not hide duplicated C/C++ algorithms. Behavior requiring C/C++ belongs in a STIG-project-owned stub, not in a selectively imported original implementation outside the configured boundary. After full collection, the heading is:

That prompt reuses still-current configuration reviews and compares both sink tables through analyzer JSON, P7 and actual HTML, keeping incomplete evidence explicit. When collection produced no usable evidence, the prompt requests diagnosis of that failure first.

Naming $stig:source-analysis is optional when the request already identifies STIG evidence and rewrite rules. stigCheckAnalysis prints the prompt for its collection mode at completion when it generated a ZIP. Without ZIP export, it prints a prompt with the actual evidence folders and their review_evidence_index.json entry points; the payloads may remain in their producing tasks' folders. Root and activity checks, including partial-result collection, select the prompt by mode.

For an initial evidence and rewrite-readiness check, then stop:

Check these evidence ZIPs for critical issues, successful artifact collection, and whether we have enough evidence to review every active rewrite rule. Identify concrete missing evidence separately from unfinished review, then stop.

For a status check using saved records, without new execution:

Use $stig:source-analysis to inspect the current rules selected by <activity> and its existing review records. Check that every use(...) resolves to a registry rule with the recorded reviewStatus, rationale and scope. Distinguish saved source status, retained P5 results and the last audited ZIP. Reconcile the latest decisions and list remaining work. Do not run Gradle, audits, generation or the analysis pipeline. Documentation edits are allowed.

For review without configuration changes:

Use $stig:source-analysis to inspect these stigCheckAnalysis evidence ZIPs. Validate the evidence, report each activity's current stage and blockers, and follow analysis-evidence.md. Check missing registry definitions and required activity use(...) entries before reviews; when configuration is ready, compare every sink through all available stages. Do not edit configuration or accept a known gap.

For an authorized alignment repair:

Use $stig:source-analysis to align <activity or evidence ZIP> from the initial LLVM module through stigGenerateHtml. Repair proven consumer configuration defects. For a STIG defect, explain the producer and proposed fix, then ask whether to prepare a Markdown issue report or also repair STIG, unless that repair is already authorized. Work stage by stage, explain required source-machine reruns, and continue independent activities. Record transform confirmations after sufficient technical review and P5 validation. Obtain my acceptance of each remaining known gap before recording it. Do not commit or push.
23 October 2026