User Guide

SDLC Execution Platform

Complete reference for installation, configuration, and all platform features.

1. Installation

Requirements: Java 17 or later. An Anthropic or OpenAI API key.

Linux / macOS

curl -fsSL https://bakalarsoftware.com/dl/install.sh | bash

Downloads the latest fat JAR to ~/.sdlc/bin/, writes an sdlc wrapper script, and adds ~/.sdlc/bin to your PATH.

Windows (PowerShell)

irm https://bakalarsoftware.com/dl/install.ps1 | iex

Downloads the JAR to %USERPROFILE%\.sdlc\bin\, writes an sdlc.bat wrapper, and adds %USERPROFILE%\.sdlc\bin to your user PATH. Restart your terminal after install, or load the new PATH immediately:

$env:PATH = "$env:USERPROFILE\.sdlc\bin;$env:PATH"

Manual install (all platforms)

Download sdlc-orchestrator.jar from bakalarsoftware.com/dl/sdlc-orchestrator.jar and run it directly. No installer needed — it is a self-contained JAR.

java -jar sdlc-orchestrator.jar --help

Verify the install

sdlc --version

2. Configuration

All configuration lives in ~/.sdlc/sdlc-local.properties. Create this file before your first run.

Minimal configuration (no Jira)

llm.anthropicApiKey=sk-ant-...

This is enough to run the pipeline using --title to provide the ticket inline.

Full configuration example

# ── LLM provider (pick one) ──────────────────────────────────────────────────
llm.anthropicApiKey=sk-ant-...
# llm.openAiApiKey=sk-...
# llm.ollamaBaseUrl=http://localhost:11434   # local embeddings via Ollama

# ── Jira (optional) ──────────────────────────────────────────────────────────
jira.baseUrl=https://yourco.atlassian.net
jira.email=you@yourco.com
jira.apiToken=<your-jira-api-token>

# ── GitHub (optional) ────────────────────────────────────────────────────────
github.token=<your-github-token>           # enables auto PR creation
# github.issuesRepo=owner/repo             # enables GitHub Issues as ticket source

# ── Linear (optional) ────────────────────────────────────────────────────────
# linear.apiKey=<your-linear-key>

# ── Slack notifications (optional) ───────────────────────────────────────────
# slack.webhookUrl=https://hooks.slack.com/services/...

# ── Email notifications (optional) ───────────────────────────────────────────
# smtp.host=smtp.gmail.com
# smtp.port=587
# smtp.username=sender@example.com
# smtp.password=<app-specific-password>
# smtp.to=recipient@example.com

# ── Approver identity (optional) ─────────────────────────────────────────────
# sdlc.approver=Alice Chen
# sdlc.approver.role=senior-engineer

# ── RBAC: require a role for high-risk intents (optional) ────────────────────
# sdlc.require.role.EXECUTION_REQUEST=senior-engineer
# sdlc.require.role.BUG_FIX=engineer

# ── Coverage gate (optional) ─────────────────────────────────────────────────
# sdlc.coverage.minimum=0.80    # pipeline fails if line coverage drops below 80%

# ── Shared audit database for multi-developer teams (optional) ───────────────
# sdlc.db.url=jdbc:sqlite:/shared/drive/sdlc-audit.db

The config file is never committed to source control — it holds credentials. Your .gitignore should exclude sdlc-local.properties and sdlc.properties.

3. Running the Pipeline

Ticket from Jira

sdlc --ticket-id PROJ-42 --project /path/to/your/project

Ticket provided inline (no Jira required)

sdlc --ticket-id PROJ-42 \
     --title "Add GET /api/users endpoint" \
     --description "As a client I need to retrieve all users from the database." \
     --project /path/to/your/project

Other common invocations

# Custom config file
sdlc --ticket-id PROJ-42 --project /path/to/project --config /path/to/sdlc-local.properties

# Force codebase rescan (skip cached index)
sdlc --ticket-id PROJ-42 --project /path/to/project --rescan

# Dry run — see the diff without applying anything
sdlc --ticket-id PROJ-42 --project /path/to/project --dry-run

What happens when you run

The pipeline proceeds through nine stages. At two points it stops and asks you to approve before continuing. Type yes to proceed or no to stop.

Ticket
  → Checkpoint 0   clarify open questions
  → Scan           index the local codebase
  → Plan           RAG + LLM generates structured plan
  → Validate       hard validation gate (automated)
  → Role gate      RBAC check (if configured)
  → Checkpoint 1   you review and approve the plan
  → CodeGen        LLM reads files, writes implementations
  → Checkpoint 2   you review and approve the generated code
  → Apply          files written to disk
  → Verify         compile + test suite runs
  → Commit         branch created, changes committed
  → PR             GitHub PR opened (if github.token configured)
  → Audit          full record written

4. Pipeline Stages Explained

Checkpoint 0 — Clarification

The LLM reads the ticket and produces a technical interpretation of the request, along with any open questions it cannot resolve from the ticket alone. You see this before any code is planned. If the ticket is ambiguous, this is where you catch it.

Scan

The platform indexes your codebase locally — controllers, services, models, dependencies — and builds a vector index for RAG retrieval. The index is cached; subsequent runs skip re-indexing unless you pass --rescan.

Plan generation

The LLM uses RAG to retrieve relevant parts of your codebase and generates a structured execution plan containing:

  • A plain-English summary of the overall change
  • A list of operations — each with an intent, a rationale, and the files it affects
  • Constraints (things that must be true before code is written)
  • Validation requirements (things that must be true after code is written)

Validation (hard gate)

An automated validator checks the plan before any human sees it. It verifies all operations have targets, no circular dependencies exist, and all referenced files are present or explicitly new. If validation fails, the pipeline stops immediately. There is no human bypass.

Role gate

If RBAC is configured, the platform checks whether the current approver's role satisfies the requirement for the detected intent type. If the role does not match, the pipeline stops with outcome REJECTED_BY_RBAC. See Section 10.

Checkpoint 1 — Plan review

The full plan is displayed in your terminal. You read it, then approve or reject. Things to look for:

  • Does the plan match what the ticket asked for?
  • Are the affected files correct?
  • Does anything in the plan seem out of scope or risky?

If you reject, the pipeline stops. No code is generated. The rejection is recorded in the audit log.

Code generation

After plan approval, the LLM reads the actual current contents of every affected file and generates complete, working implementations. No stubs. No TODOs. It writes the file as it should look after the change.

Checkpoint 2 — Diff review

The generated code is displayed as a unified diff. You read it, then approve or reject. Things to look for:

  • Does the generated code match the plan?
  • Are there any issues a reviewer would flag in a PR?
  • Is anything unexpected being changed?

If you pass --dry-run, the pipeline stops here without writing anything.

Apply

Generated file contents are written to disk. Nothing is applied before this point.

Verify

The platform runs your build and test suite based on the detected project type:

Project typeVerifier command
Spring Boot / Mavenmvn clean compile test
Gradlegradle build
Node / TypeScriptnpm test
Pythonpytest

If the build fails, the pipeline stops with EXECUTION_FAILED. If sdlc.coverage.minimum is configured and coverage falls below the threshold, the pipeline also fails.

Commit, PR, and audit

On success, the platform:

  1. Creates a branch named <ticket-id> (e.g., PROJ-42)
  2. Commits all generated files with message [PROJ-42] Ticket Title
  3. Opens a GitHub PR from that branch to main (if github.token is configured)
  4. Writes a full audit record to ~/.sdlc/audit/
  5. Transitions the Jira ticket to "In Review" (if Jira is configured)
  6. Sends notifications if --notify is passed and Slack/email are configured

5. Project Type Support

The platform auto-detects your project type by looking for these files in the project root:

OrderFiles checkedDetected type
1tsconfig.json and package.jsonNode / TypeScript
2requirements.txt or pyproject.tomlPython
3build.gradle or build.gradle.ktsGradle
4pom.xmlSpring Boot / Maven
5package.json (fallback)Node / TypeScript

To override detection:

sdlc --ticket-id PROJ-42 --project /path --project-type python

Accepted values: spring-boot, spring, maven, gradle, node-typescript, node, typescript, ts, nestjs, express, python, py.

To override only the build verifier independently of the scanner:

sdlc --ticket-id PROJ-42 --project /path --build-system gradle

6. Ticket Sources

Jira (default)

Configure jira.baseUrl, jira.email, and jira.apiToken. The platform fetches the ticket automatically.

sdlc --ticket-id PROJ-42 --project /path/to/project

Linear

Set linear.apiKey in your config. The platform auto-detects Linear when the key is present.

sdlc --ticket-id ENG-123 --project /path/to/project
# or explicitly:
sdlc --ticket-id ENG-123 --project /path/to/project --ticket-source linear

GitHub Issues

Set github.token and github.issuesRepo=owner/repo in your config.

sdlc --ticket-id 42 --project /path/to/project
# or explicitly:
sdlc --ticket-id 42 --project /path/to/project --ticket-source github

Manual (no ticket system)

Skip ticket ingestion entirely by providing the ticket inline. No credentials needed.

sdlc --ticket-id LOCAL-1 \
     --title "Refactor UserService to use repository pattern" \
     --description "Extract database calls from UserService into a UserRepository." \
     --project /path/to/project

Auto-detection order

When --ticket-source is not specified, the platform selects in this order: Linear (if linear.apiKey is set) → GitHub Issues (if both github.token and github.issuesRepo are set) → Jira (fallback).

7. Audit Log

Every pipeline run — including rejections, failures, and dry runs — produces a complete audit record.

Location

~/.sdlc/audit/<TICKET-ID>-<YYYYMMDD-HHMMSS>.json

What is recorded

FieldDescription
ticketId, ticketTitleThe ticket that was processed
startedAt, completedAtISO 8601 timestamps
outcomeFinal outcome (see outcomes below)
intentTypeHow the LLM classified the ticket
planSummaryHigh-level plan description
planOperationsAll plan operations with intent, rationale, affected files
planApproverName of the person who approved the plan
codeApproverName of the person who approved the code
generatedDiffFull generated file contents
executedOperationsList of files written to disk
gitBranch, gitCommitShaBranch and commit SHA
prUrlGitHub PR URL
coverageLine coverage %, covered lines, total lines, report path
metricsWall clock duration, LLM model, token counts, estimated cost
eventsTimestamped log of every pipeline event
validationErrorsValidation failures (if any)
failureReasonHuman-readable failure description

Possible outcomes

OutcomeWhat it means
SUCCESSPipeline completed; code applied, verified, and committed
DRY_RUNRan with --dry-run; diff generated but not applied
REJECTED_BY_HUMANDeveloper rejected the plan at Checkpoint 1
ABORTED_AT_DIFFDeveloper rejected the code at Checkpoint 2
REJECTED_BY_VALIDATIONAutomated validation gate failed
REJECTED_BY_RBACApprover role did not satisfy the configured requirement
EXECUTION_FAILEDBuild or test suite failed after applying changes
PLAN_GENERATION_FAILEDLLM could not produce a valid plan
NON_EXECUTABLE_INTENTTicket intent was analysis or investigation, not a code change

Viewing audit records

# List the 20 most recent runs
sdlc --list-audits

# Show the full record for a ticket
sdlc --show-audit PROJ-42

Shared audit database

For multi-developer teams, point all instances at a shared SQLite database:

sdlc.db.url=jdbc:sqlite:/shared/drive/sdlc-audit.db

Audit JSON is written to both the local file and the shared database. The web dashboard can read from either.

8. Web Dashboard

sdlc --serve
# Open http://localhost:7070

List view

Shows all pipeline runs with summary stats (total runs, success rate, average duration, total cost) and a filterable table. Filters: ticket ID search, outcome dropdown, date range.

Detail view

Click any row to open the full audit record: ticket metadata and outcome, approver identities, git branch and commit SHA, PR link, LLM model and cost, code coverage, the full execution plan, and the generated diff file by file.

9. Compliance Reports

SOC2 Type II evidence report

# Single ticket (text)
sdlc --export-report PROJ-42

# Single ticket (PDF)
sdlc --export-pdf-report PROJ-42

# All tickets
sdlc --export-all

# All tickets since a date (PDF)
sdlc --export-all-pdf --since 2026-01-01
Pipeline stageSOC2 controlEvidence
Plan approvalCC6.6 Change AuthorizationPlan approved by: [name]
Code review and approvalCC6.2 Separation of DutiesCode approved by: [name]
Build and test verificationCC8.1 Testing and QATests passed; coverage X%
Audit trailCC7.2 Audit TrailWritten to ~/.sdlc/audit/

HIPAA change management record

sdlc --export-hipaa-report PROJ-42
sdlc --export-hipaa-pdf-report PROJ-42
sdlc --export-all-hipaa
sdlc --export-all-hipaa-pdf --since 2026-01-01
Pipeline stageHIPAA sectionEvidence
Change authorization§164.308(a)(5) SecurityApproved by: [name]
Separation of duties§164.308(a)(3) WorkforceCode reviewed by: [name]
Build and test§164.312(c)(1) IntegrityTests passed; coverage X%
Audit trail§164.312(b) Audit ControlsWritten to ~/.sdlc/audit/
Dual approval gate§164.312(a)(1) Access ControlPipeline enforces dual approval

Output location

~/.sdlc/audit/reports/<TICKET-ID>-report.txt
~/.sdlc/audit/reports/<TICKET-ID>-report.pdf
~/.sdlc/audit/reports/<TICKET-ID>-hipaa.txt
~/.sdlc/audit/reports/<TICKET-ID>-hipaa.pdf

10. Role-Based Access Control

RBAC lets you require a specific approver role for certain types of changes. It is checked automatically after plan validation and before the plan is shown to the user.

Configuration

# Declare who is running the platform
sdlc.approver=Alice Chen
sdlc.approver.role=senior-engineer

# Require senior-engineer for new features and endpoints
sdlc.require.role.EXECUTION_REQUEST=senior-engineer

# Require any engineer for bug fixes
sdlc.require.role.BUG_FIX=engineer

Intent types

Intent typeTypical ticket
EXECUTION_REQUESTNew feature, new endpoint, new service
BUG_FIXFix a defect, correct behavior
ANALYSIS_REQUESTInvestigate or explain — no code change
INVESTIGATIONDiagnose an issue
NON_TECHNICALDocumentation, process, not a code task

Behavior

  • If no requirement is configured for the detected intent type, any approver can proceed.
  • If a requirement exists and the approver's role matches, the pipeline continues.
  • If a requirement exists and the approver has no role, or the role does not match, the pipeline stops with REJECTED_BY_RBAC.
  • The RBAC check result is recorded in the audit log.

Regardless of RBAC, the audit log always records planApprover and codeApprover. Identity comes from sdlc.approver in config, or falls back to the USER environment variable.

11. Notifications

Configuration

# Slack
slack.webhookUrl=https://hooks.slack.com/services/T.../B.../...

# Email
smtp.host=smtp.gmail.com
smtp.port=587
smtp.username=sender@example.com
smtp.password=<app-specific-password>
smtp.to=recipient@example.com

Enabling notifications

sdlc --ticket-id PROJ-42 --project /path/to/project --notify

What triggers a notification

Notifications are sent for three outcomes only: SUCCESS, EXECUTION_FAILED, and REJECTED_BY_VALIDATION. Rejections by the developer and dry runs do not send notifications.

SDLC Pipeline Result
Ticket:   PROJ-42
Outcome:  SUCCESS
PR:       https://github.com/your-org/your-repo/pull/123
Commit:   abc123def456...
Duration: 45.3s
Est. cost: $0.0234 USD

Notification failures (unreachable webhook, SMTP error) are logged as warnings and do not affect the pipeline outcome.

12. Metrics

sdlc --metrics

Aggregates statistics across all audit records in ~/.sdlc/audit/:

  • Total runs — count of all pipeline executions
  • Successful — count and percentage of SUCCESS outcomes
  • Per-outcome breakdown — count of each failure type
  • Average duration — mean wall-clock time across successful runs (seconds)
  • LLM models used — how many runs used each model
  • Total tokens — aggregate prompt and completion tokens across all runs
  • Total cost — sum of estimated LLM costs across all runs (USD)
  • Coverage — average and minimum line coverage percentage across successful runs

13. CI/CD Integration

GitHub Actions

A ready-to-use workflow is included at .github/workflows/sdlc-platform.yml. Use --non-interactive to auto-approve both checkpoints — the human review happens in the PR the platform opens.

- name: Run SDLC pipeline
  run: |
    sdlc --ticket-id "${{ env.TICKET_ID }}" --project . --non-interactive
  env:
    ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}

Exit codes

Exit codeMeaning
0SUCCESS or DRY_RUN
1Any failure or rejection

Jenkins

Run the platform as a shell step. Use --non-interactive and check the exit code. The platform returns 1 on any failure.

14. Docker

Image: ghcr.io/gbakalar/sdlc-platform:latest

Basic run

docker run --rm \
  -v ~/.sdlc:/root/.sdlc \
  -v /path/to/your/project:/project \
  ghcr.io/gbakalar/sdlc-platform:latest \
  --ticket-id PROJ-42 --project /project

With an explicit config path

docker run --rm \
  -v ~/.sdlc:/root/.sdlc \
  -v /path/to/your/project:/project \
  ghcr.io/gbakalar/sdlc-platform:latest \
  --ticket-id PROJ-42 --project /project --config /root/.sdlc/sdlc-local.properties

Volumes

MountPurpose
~/.sdlc:/root/.sdlcConfig file and audit log storage
/path/to/project:/projectTarget codebase

15. CLI Reference

Pipeline

FlagDescription
--ticket-id IDTicket identifier to process
--title "text"Ticket title (skips Jira fetch when provided)
--description "text"Ticket description (used with --title)
--project /pathPath to the target project root
--config /pathPath to the config file
--ticket-source jira|linear|githubOverride ticket source auto-detection
--project-type TYPEOverride project type auto-detection
--build-system TYPEOverride build verifier independently
--rescanForce codebase rescan (ignore cached index)

Pipeline control

FlagDescription
--dry-runGenerate and display diff without applying changes
--non-interactiveAuto-approve both checkpoints (for CI)
--no-gitSkip branch creation and commit
--notifySend Slack/email notification on completion

Audit and history

FlagDescription
--list-auditsList the 20 most recent audit records
--show-audit IDShow the full audit record for a ticket
--metricsShow aggregate stats across all audits
--serveStart the web dashboard at http://localhost:7070

Compliance reports

FlagDescription
--export-report IDExport SOC2 report (text) for one ticket
--export-hipaa-report IDExport HIPAA report (text) for one ticket
--export-pdf-report IDExport SOC2 report (PDF) for one ticket
--export-hipaa-pdf-report IDExport HIPAA report (PDF) for one ticket
--export-allBatch export SOC2 reports (text)
--export-all-hipaaBatch export HIPAA reports (text)
--export-all-pdfBatch export SOC2 reports (PDF)
--export-all-hipaa-pdfBatch export HIPAA reports (PDF)
--since YYYY-MM-DDFilter batch exports by date (inclusive)

Utilities

FlagDescription
--version, -vPrint version and exit
--help, -hPrint all flags and examples

16. Config Reference

All properties go in ~/.sdlc/sdlc-local.properties unless --config specifies another path.

LLM

PropertyDescription
llm.anthropicApiKeyAnthropic API key (uses claude-sonnet-4-6)
llm.openAiApiKeyOpenAI API key (uses gpt-4o)
llm.ollamaBaseUrlOllama base URL for local embeddings (optional)

Jira

PropertyDescription
jira.baseUrlJira instance URL (e.g., https://yourco.atlassian.net)
jira.emailJira account email
jira.apiTokenJira API token

GitHub

PropertyDescription
github.tokenGitHub personal access token (enables auto PR creation)
github.issuesRepoGitHub repo for ticket ingestion (e.g., owner/repo)

Linear

PropertyDescription
linear.apiKeyLinear API key

Notifications

PropertyDescription
slack.webhookUrlSlack Incoming Webhook URL
smtp.hostSMTP server hostname
smtp.portSMTP port (default: 587)
smtp.usernameSMTP username
smtp.passwordSMTP password
smtp.toNotification recipient email

Approver and RBAC

PropertyDescription
sdlc.approverApprover display name (recorded in audit)
sdlc.approver.roleApprover role for RBAC checks
sdlc.require.role.<INTENT_TYPE>Required approver role for a specific intent type

Quality and audit

PropertyDescription
sdlc.coverage.minimumMinimum required line coverage (0.0–1.0); pipeline fails if below this
sdlc.db.urlSQLite JDBC URL for shared audit database

17. Troubleshooting

"could not determine latest release" during install

The install script fetches the latest tag from the GitHub API. Check your internet connection. If you are behind a proxy, set https_proxy before running the script.

Pipeline fails immediately with "config validation failed"

The platform validates the config on startup. Check that at least one LLM key (llm.anthropicApiKey or llm.openAiApiKey) is present, Jira config is complete if Jira is your ticket source, and there are no trailing spaces in property values.

"REJECTED_BY_VALIDATION" on every run

The plan validator found a problem. Check the validationErrors field in the audit record (sdlc --show-audit TICKET-ID). Common causes: ticket description is too vague (add more detail to --description), or the LLM hallucinated a file path (run --rescan to refresh the index).

Build fails after apply

The generated code has a compile or test error. The failureReason field in the audit record has the verifier output. Common causes: project type misdetected (use --project-type to override), or a stale codebase index (try --rescan).

No GitHub PR is created

github.token must be set in config and the local repo must have a main branch and a configured remote. The platform logs a warning and continues if PR creation fails.

Jira ticket not transitioning to "In Review"

The platform looks for a transition named "In Review" in your Jira workflow. If your workflow uses a different name, the transition is skipped and a warning is logged. The pipeline still completes successfully.

Notifications not arriving

  • Verify slack.webhookUrl is the full webhook URL including the path.
  • For Gmail, use an App Password rather than your account password.
  • Check the events array in the audit JSON — it includes notification delivery logs.

Web dashboard shows no data

The dashboard reads from ~/.sdlc/audit/. Confirm that directory contains .json files. If you configured sdlc.db.url, pass the same --config file to --serve so the dashboard knows where the database is.