For AI agents: the complete documentation index is available at https://docs.flezise.com/llms.txt, the full documentation bundle is available at https://docs.flezise.com/llms-full.txt, and this page is available as Markdown at https://docs.flezise.com/work-items/playbooks.md.

Playbooks

A playbook is the list of steps a work item goes through, from triage to merge. You change it in your repository to add checks your company needs (a PCI DSS scan, a HIPAA review), run steps of your own (a skill that simplifies the change, an SAP transport), and tell people or other systems what happened.

Every project starts with two default playbooks: Ticket for bugs, features, questions and tasks, and Spec Build for the build of an approved spec. Each work item shows its playbook's steps at the top of its Overview (see Work the board).

Where a playbook lives

Add .sdlc/playbooks.yaml to the default branch of your project's repository. It holds a playbooks: list; a playbook whose applies_to.work_types names an item's type replaces the default for that type. Triage's classification is the type of a ticket (bug, feature, question, task); a spec build is implementation.

A playbook that does not validate is ignored, and the default runs instead. The run's log names the playbook and the reason.

The steps

A ticket and a spec build keep their fixed points, in this order. Between the change and its pull request, and between the pull request and the review, you add steps of your own.

FlowFixed steps, in order
Tickettriage, approval (the plan), implement, your steps, open_pr, your notices, approval (the review), wait_for_merge
Spec buildimplement, your steps, open_pr, your notices, approval (the review), wait_for_merge

The steps you add:

usesWhat it doesFails the run when
gatesRuns the checks named in run, in that order. A failed check goes back to the agent to fix, and the checks run again (always in a spec build; in a ticket with fix: true).A spec build's checks still fail after the fix budget. A ticket's failed checks go to review.
agentOne more instruction to the agent: a prompt, a skill to follow, or both.The skill is not installed for the project.
scriptRuns the command in run in the agent's sandbox.The command exits non-zero.
httpCalls url (https, public hosts only) with the item, the changed files and the risk level.The answer is not 2xx, or its JSON says "passed": false.
notifySends message to people's inbox (to: owner, assignees, project_members), the ticket in Jira or Linear (channels: [source_ticket]), or the pull request (channels: [pull_request]).Never.

A fix turn, or an agent or script step that edits files, sends the run back to the first gates step, so every check passes on the final code. All gates steps share one fix budget, so a run always ends.

After open_pr, only notify and http steps can follow, and their failures are recorded without undoing the change.

Checks

A gates step names the platform's checks and your own. The platform's are preflight, ac_coverage, verifier, browser_verification and code_review in a spec build, and tests and preview in a ticket. Each also has to be switched on for your Flezise installation.

Your own checks go under checks::

KindPasses when
script: <command>The command exits 0 in the sandbox. Its output goes to the agent when it fails.
agent: <what to check>, optionally skill: <name>A separate reviewer session reads the change and writes a verdict. Its findings go to the agent when it fails.
http: <url>Your service answers 2xx without "passed": false.

Each check shows under Verifications with its result. A check you leave out of every gates step does not run and does not show.

Conditions and risk

when: on a step or a check runs it only when the condition holds; otherwise the step shows as skipped, with the reason. Conditions read named facts only:

FactExample
riskrisk >= medium (levels low, medium, high, critical)
touches(area, ...)touches(payments, auth): a changed file is in one of the areas
labels(...)labels(security)
work_typework_type == bug
diff.lines_changed, diff.files_changeddiff.lines_changed > 400
dependencies_changed, ci_changeda manifest, lockfile or CI file changed

Combine them with and, or, not and parentheses. Before the change exists, touches reads the areas the ticket names by label or in its text. After it, an area the ticket is labelled with still counts as touched, so a phi label keeps the PHI checks even when the code lands outside the paths you mapped.

risk: rules set the level. The highest level with a matching rule wins, and the item shows the level and its reasons next to its steps. With ai_assessment: raise_only (the default) the level triage assessed can raise it, never lower it. Risk is assessed at triage and again after the change; a condition reads the latest.

A when: on the plan approval decides whether a person approves the plan. A when: on a ticket's review decides whether a verified fix with a pull request is accepted on its own. Changes to CI or check files and failed checks always go to a person.

Areas

Areas are names for parts of a codebase. Each stack Flezise supports maps common ones (auth, api, ui, migrations, infra, config, tests), and dependencies, ci and docs work for any stack. Add or override areas in .sdlc/areas.yaml:

areas:
  payments: ["services/billing/**", "libs/card-vault/**"]
  phi: ["src/patients/**", "src/records/**"]

A rule that names an area your project does not map is false, and the risk shows the area as not mapped.

Your own step types

step_types: defines a step once, built on agent, script, http or notify, with inputs a step fills in with with:. Use it for systems Flezise does not know about.

Secrets

An http step or check can send headers that name a secret as ${secret:NAME}. Flezise reads it from the project's Vault path projects/<project id>/playbook. A missing secret fails the step.

Example: a payments team

playbooks:
  - id: pci-bug-fix
    name: PCI Bug Fix
    applies_to: {work_types: [bug]}
    risk:
      high:
        - touches: [payments]
        - diff.lines_changed > 400
      medium:
        - dependencies_changed
    checks:
      pan-scan:
        name: Card number scan
        script: "! grep -rEn '\\b[0-9]{13,16}\\b' src"
      pci-review:
        name: PCI DSS review
        agent: Check the change against PCI DSS requirements 3 and 6 (stored card data, input validation, secure coding).
        when: touches(payments)
    steps:
      - {id: triage, uses: triage}
      - {id: approve-plan, uses: approval, when: "risk >= medium"}
      - {id: implement, uses: implement}
      - {id: checks, uses: gates, run: [tests, pan-scan, pci-review], fix: true}
      - {id: pr, uses: open_pr}
      - id: tell-security
        uses: notify
        when: "risk >= high"
        message: "{display_id} touches payments: {pr_url}"
        to: [project_members]
        channels: [inbox, source_ticket]
      - {id: review, uses: approval}
      - {id: merged, uses: wait_for_merge}

Example: a spec build that ships to SAP

playbooks:
  - id: sap-build
    name: SAP Spec Build
    applies_to: {work_types: [implementation]}
    step_types:
      sap-transport:
        kind: script
        run: "abapgit-cli push --package {{ inputs.package }} --system {{ inputs.system }}"
        inputs:
          package: {}
          system: {default: DEV}
    checks:
      hipaa-review:
        agent: Check that no patient data leaves the PHI services and that every access is logged.
        when: touches(phi)
    steps:
      - {id: build, uses: implement, name: Build}
      - {id: simplify, uses: agent, skill: code-review, prompt: Simplify the change without changing behaviour.}
      - {id: checks, uses: gates, run: [preflight, hipaa-review, ac_coverage]}
      - {id: transport, uses: sap-transport, with: {package: ZFI_INVOICE}}
      - {id: ui-checks, uses: gates, run: [verifier, code_review], when: touches(ui)}
      - {id: pr, uses: open_pr}
      - id: change-record
        uses: http
        url: https://change.example.com/api/records
        headers: {Authorization: "Bearer ${secret:CHANGE_TOKEN}"}
      - {id: review, uses: approval}
      - {id: merged, uses: wait_for_merge}

Next steps