// Moved from docs/src/ci-cd/JENKINS_GOVERNANCE_INTEGRATION.adoc to docs/working/scratch/src/ci-cd/JENKINS_GOVERNANCE_INTEGRATION.adoc on 2026-06-16 (docs reorg Phase 2)
= Jenkins Governance Integration Guide
:doctype: article
:toc:
:toc-placement: preamble
:sectnums:
:sectanchors:
:source-highlighter: highlightjs

== Document Information

[cols="1,3"]
|===
|Document Version|1.0.0
|Document Date|2025-11-03
|Status|Governance Integration Specification
|Classification|CI/CD Process Documentation
|===

== Overview

This document specifies how **Jenkins pipeline jobs** must integrate with the **StarForth governance system** by routing all outputs to the `in_basket` gating mechanism as the single entry point for governance-relevant artifacts.

**Core Principle:** All governance inputs, regardless of source (GitHub Actions OR Jenkins), MUST flow through:

```
Development Output (Jenkins Job)
    ↓
in_basket/ (Single Gating Point)
    ↓
QA Triage (per INTAKE_PROCEDURES.adoc)
    ↓
[VAULT] Disposition
```

== Jenkins Jobs in StarForth Pipeline

The StarForth CI/CD pipeline includes three primary Jenkins jobs:

[cols="1,1,1,2"]
|===
|Job Name|Trigger|Purpose|Artifacts to Vault
|`starforth-devl`|Webhook (PR on devl)|Build + Smoke Test|Build log, test summary
|`starforth-test`|Auto-triggered after devl|Full test suite execution|Test results, coverage metrics
|`starforth-qual`|Auto-triggered after test|Formal verification, benchmarks|Benchmarks, SBOM, verification reports
|===

== Governance Integration Requirements

=== 1. SSH/Git Access to StarForth-Governance

Each Jenkins job that produces governance artifacts **MUST** have:

1. **SSH credentials** configured in Jenkins for StarForth-Governance repo
2. **Read/Write access** to the governance repository
3. **Submodule permissions** (if StarForth-Governance is a submodule)

**Configuration:**
```groovy
// In Jenkinsfile or Job DSL:
credentials {
  sshUserPrivateKey('starforth-governance-ssh', 'Jenkins SSH Key for StarForth-Governance')
}
```

=== 2. Cloning StarForth-Governance Submodule

Each job must initialize the governance repo for artifact staging:

```groovy
stage('Setup Governance Path') {
    steps {
        script {
            // Initialize submodule
            sh '''
                git submodule update --init --recursive
                # Verify governance repo is accessible
                ls -la StarForth-Governance/in_basket/
            '''
        }
    }
}
```

=== 3. Artifact Routing Pattern

All Jenkins jobs MUST follow this pattern when generating governance artifacts:

```groovy
stage('Route Artifacts to Governance') {
    steps {
        script {
            sh '''
                # Ensure in_basket subdirectories exist
                mkdir -p StarForth-Governance/in_basket/Test_Results
                mkdir -p StarForth-Governance/in_basket/Performance_Data
                mkdir -p StarForth-Governance/in_basket

                # Generate submission metadata
                SUBMISSION_ID="JENKINS-$(date +%Y%m%d-%H%M%S)"
                TIMESTAMP=$(date -u +'%Y-%m-%dT%H:%M:%SZ')

                # Copy artifacts with metadata
                # (See examples below for each job type)
            '''
        }
    }
}
```

== Job-Specific Governance Integration

=== starforth-devl Job

**Outputs:** Build log, smoke test results

**Routing:**

```groovy
post {
    always {
        // Publish build log to in_basket
        script {
            sh '''
                SUBMISSION_ID="DEVL-$(date +%Y%m%d-%H%M%S)"
                VAULT_PATH="StarForth-Governance/in_basket/Test_Results"
                mkdir -p "$VAULT_PATH"

                # Copy build artifacts
                cp -r build/logs "$VAULT_PATH/${SUBMISSION_ID}_build_log/" || true
                cp build/*.log "$VAULT_PATH/${SUBMISSION_ID}_build.log" || true

                # Create submission metadata
                cat > "$VAULT_PATH/${SUBMISSION_ID}_DEVL_SUMMARY.adoc" << EOF
                = Jenkins DevL Build Results
                :submission-id: $SUBMISSION_ID
                :submission-date: $(date -u +'%Y-%m-%dT%H:%M:%SZ')

                == Build Status
                - Build: ${BUILD_RESULT:-UNKNOWN}
                - Smoke Test: PASS/FAIL
                - Artifacts: build/starforth (x86_64-linux-gnu)

                == Disposition
                Submitted by:: Jenkins starforth-devl job
                Status:: Awaiting QA Triage
                Pathway:: Test_Results
                SLA:: 3 business days

                == References
                - Jenkins: ${BUILD_URL}
                - PR: ${CHANGE_URL:-N/A}
                EOF

                echo "✅ DevL artifacts routed to governance: $VAULT_PATH"
            '''
        }
    }
}
```

=== starforth-test Job

**Outputs:** Test suite results, logs, pass/fail metrics

**Routing:**

```groovy
post {
    always {
        // Publish test results to in_basket
        script {
            sh '''
                SUBMISSION_ID="TEST-$(date +%Y%m%d-%H%M%S)"
                VAULT_PATH="StarForth-Governance/in_basket/Test_Results"
                mkdir -p "$VAULT_PATH"

                # Copy test artifacts
                cp -r test-results "$VAULT_PATH/${SUBMISSION_ID}_test_results/" || true
                cp -r logs "$VAULT_PATH/${SUBMISSION_ID}_logs/" || true

                # Generate test summary
                cat > "$VAULT_PATH/${SUBMISSION_ID}_TEST_SUMMARY.adoc" << EOF
                = Jenkins Test Results
                :submission-id: $SUBMISSION_ID
                :submission-date: $(date -u +'%Y-%m-%dT%H:%M:%SZ')

                == Test Execution

                [cols="1,1,1"]
                |===
                |Test Suite|Result|Coverage
                |Unit Tests|${TEST_COUNT_PASS}/${TEST_COUNT_TOTAL}|${TEST_COVERAGE}%
                |Integration|PASS/FAIL|N/A
                |Regression|PASS/FAIL|Full suite
                |===

                == Disposition
                Submitted by:: Jenkins starforth-test job
                Status:: Awaiting QA Evaluation
                Pathway:: Test_Results
                SLA:: 3 business days

                == References
                - Jenkins: ${BUILD_URL}
                - Branch: ${GIT_BRANCH}
                - Commit: ${GIT_COMMIT}
                EOF

                echo "✅ Test results routed to governance: $VAULT_PATH"
            '''
        }
    }
}
```

=== starforth-qual Job

**Outputs:** Benchmarks, SBOM, formal verification reports

**Routing:**

```groovy
post {
    always {
        // Publish QUAL artifacts to in_basket
        script {
            sh '''
                SUBMISSION_ID="QUAL-$(date +%Y%m%d-%H%M%S)"
                PERF_PATH="StarForth-Governance/in_basket/Performance_Data"
                SBOM_PATH="StarForth-Governance/in_basket"
                mkdir -p "$PERF_PATH"

                # Copy benchmark results
                cp -r builds/benchmark "$PERF_PATH/${SUBMISSION_ID}_benchmark/" || true

                # Copy SBOM
                cp -r builds/sbom "$SBOM_PATH/${SUBMISSION_ID}_sbom/" || true

                # Copy verification reports
                cp -r verification-reports "$PERF_PATH/${SUBMISSION_ID}_verification/" || true

                # Generate QUAL summary
                cat > "$PERF_PATH/${SUBMISSION_ID}_QUAL_SUMMARY.adoc" << EOF
                = Jenkins QUAL Stage Results
                :submission-id: $SUBMISSION_ID
                :submission-date: $(date -u +'%Y-%m-%dT%H:%M:%SZ')

                == Benchmark Results

                [cols="1,1,1"]
                |===
                |Metric|Value|Status
                |Throughput|${THROUGHPUT_VALUE}|${THROUGHPUT_STATUS}
                |Latency P50|${LATENCY_P50}ms|${LATENCY_STATUS}
                |Memory Usage|${MEMORY_MB}MB|OK
                |===

                == SBOM
                - Generated: YES
                - Format: SPDX
                - Location: ${SUBMISSION_ID}_sbom/

                == Disposition
                Submitted by:: Jenkins starforth-qual job
                Status:: Awaiting QA Evaluation
                Pathway:: Performance_Data + Compliance_Evidence
                SLA:: 5 business days (performance), 7 business days (SBOM)

                == References
                - Jenkins: ${BUILD_URL}
                - Build ID: ${BUILD_ID}
                - Previous stages: DevL✅ Test✅
                EOF

                echo "✅ QUAL results routed to governance"
            '''
        }
    }
}
```

== Best Practices

=== 1. Consistent Submission IDs

Always generate unique submission IDs with timestamp to avoid collisions:

```groovy
SUBMISSION_ID = "${JOB_NAME}-${BUILD_ID}-$(date +%Y%m%d-%H%M%S)"
```

=== 2. Metadata Documentation

Every submission **MUST** include a summary document (`.adoc` format) with:
- Submission ID and date
- Source (Jenkins job name, run ID)
- Artifact list and locations
- Disposition pathway (per INTAKE_PROCEDURES.adoc)
- SLA for QA triage

=== 3. Audit Trail

Maintain traceable links back to Jenkins:
- Jenkins build URL in metadata
- Commit hash and branch
- Build parameters and environment

=== 4. Error Handling

Ensure `post` blocks run even on failure:

```groovy
post {
    always {  // Not 'success' - we need records even when tests fail
        script {
            // Route results to in_basket
        }
    }
}
```

=== 5. Logging

Log all routing operations for troubleshooting:

```groovy
echo "✅ Successfully routed artifacts"
echo "📁 Location: $VAULT_PATH"
echo "📋 Submission ID: $SUBMISSION_ID"
ls -la "$VAULT_PATH"
```

== Verification Checklist

For each Jenkins job modification, verify:

- [ ] `git submodule update --init --recursive` runs before routing
- [ ] `StarForth-Governance/in_basket/` directory exists and is accessible
- [ ] Submission ID includes timestamp to avoid collisions
- [ ] Metadata document (`.adoc` format) created with all required fields
- [ ] Artifacts copied to correct in_basket subdirectory
- [ ] Post block uses `always`, not `success` only
- [ ] Logging shows successful routing
- [ ] Jenkins has SSH credentials for governance repo

== Security Considerations

=== SSH Key Management

- **Where:** Jenkins credentials (Manage Jenkins → Credentials)
- **Who:** Jenkins admin, shared with devops team
- **Rotation:** Per security policy (recommend: quarterly)
- **Access:** Only Jenkins service account should have access

=== Governance Repo Permissions

- Jenkins account needs: Read + Write to StarForth-Governance
- No broad public access
- Restrict branch protection rules if needed

=== Artifact Sensitivity

Some artifacts may contain sensitive data (performance metrics, internal timing info):
- Mark in metadata if sensitive
- Control access via repository permissions
- Document in security policy

== Troubleshooting

=== Submodule Not Initialized

```
Error: StarForth-Governance not found
Solution: Ensure 'git submodule update --init' runs before routing
```

=== Permission Denied Writing to Vault

```
Error: Permission denied: StarForth-Governance/in_basket/
Solution: Verify Jenkins SSH key has write access to governance repo
         Check repo permissions: Settings → Collaborators
```

=== Artifacts Not Found

```
Error: No such file or directory: builds/benchmark
Solution: Use 'continue-on-error: true' or '|| true' in copy commands
         Some artifacts (benchmarks, SBOM) may not exist in all runs
```

== References

- **INTAKE_PROCEDURES.adoc** - Full governance intake workflow
- **GOVERNANCE_REFERENCE_MANUAL.adoc** - Master governance document
- **test-stage.yml** - GitHub Actions test routing (reference example)
- **qual-stage.yml** - GitHub Actions QUAL routing (reference example)
- **Groovy Job DSL Examples** - jenkins/jobs/*.groovy

== Change History

[cols="1,1,1,2"]
|===
|Version|Date|Author|Changes
|1.0.0|2025-11-03|Claude Code|Initial governance integration specification
|===

== Approval

**Prepared By:** StarForth Governance System
**Date:** 2025-11-03
**Status:** Ready for Jenkins Administration Review