ai-dlc development workflow¶
Take a piece of work from an idea to an evidence-gated finish, and know which stage owns which artifact along the way.
Tool names are kept in the tool map so providers can change without redefining the lifecycle. ai-dlc prepares tools, structure and guidance for the chosen harness; agents invoke installed provider tools directly.
Use the greenfield guide for a new application and the brownfield guide for an existing repository. The design-to-implementation guide covers the handoff from an approved design to code.
Workflow at a glance¶
- Intake and priority
- Discovery
- Product requirements
- Product and technical design
- Formal specification, when the design decides one is needed
- Reviewed work record
- Branch and implementation
- Tests and required checks
- Review and merge
- Merged-revision CI evidence
- Evidence-gated finish
- Tracker completion and handoff
ai-dlc does not host an autonomous orchestrator. The human and agent decide what work is useful; skills provide judgment, and the CLI validates, links and gates the resulting work.
Stage contracts¶
| Stage | Durable output | Exit condition |
|---|---|---|
| Intake | Tracker item or reviewed candidate | The next investigation is explicit |
| Discovery | Bounded problem statement | The problem is clear enough to define or stop |
| Product requirements | Reviewed PRD when the change needs one | Material product questions are resolved or named |
| Design | Design document, diagram and linked decisions | Implementers can act without inventing product behavior |
| Specification decision | Recorded decision and, when required, provider-owned specification | Required scenarios and acceptance criteria are current |
| Work publication | .ai-dlc/work/<id>.toml and tracker item |
The record is reviewed before external mutation |
| Implementation | Code, tests, migrations and updated durable docs | Local required checks pass |
| Review and merge | Reviewed pull request and merged revision | Review, repository rules and fresh checks pass against the current target branch |
| Verification and finish | CI receipts and optional deployment evidence | ai-dlc work finish <work-id> accepts every configured gate |
| Continuity | Handoff, runbook updates and linked personal notes | Remote state and remaining work are unambiguous |
Each stage consumes reviewed output from the previous stage. A stage may decide an artifact is unnecessary; silently replacing it with assumptions is not allowed.
Design to implementation ownership¶
Skills own discovery, requirements, design judgment and the specification decision. The CLI owns reviewed work records, local checks, machine lifecycle commands and completion gates; local MCP exposes a subset of them. The handoff is complete only when the approved design, any required specification and the reviewed work record let implementation proceed without inventing behavior.
Environment preparation¶
Start a session with ai-dlc next (or context --brief) for local next
actions and required checks; it does not consult the tracker. The session-start
hook includes its first ten summary lines.
Use the machine enrollment runbook for private profiles, readiness and client setup, and the GitHub or Jira runbook for the provider. The lifecycle below stays independent of the selected provider.
Explicit project commands¶
Setup steps, their optional verify commands, and [checks.commands] accept the same three forms:
[checks.commands]
legacy = "python scripts/check_tests.py"
portable = { argv = ["python", "scripts/check_tests.py"] }
windows = { shell = "powershell", script = "& python scripts/check_tests.py; exit $LASTEXITCODE" }
Strings keep their POSIX sh -c meaning on every OS. An argv record passes each
argument literally without shell expansion. Explicit shells are posix and
powershell; scripts must propagate native exit codes themselves. A missing
executable or shell is reported, never substituted.
The argv and shell forms need an engine built after v0.4.0, and they do not make Windows a supported host; see release limits.
Sources of truth¶
- The repository owns architecture, product rationale, design context, decisions, runbooks, code, and tests.
- The configured specification provider exclusively owns formal behavior specifications. Repository design documents link to specifications instead of copying them.
- The selected delivery tracker owns engineering priority and lifecycle status. When an upstream business tracker is used, it owns business priority, outcome scope and acceptance; see GitHub delivery with Jira outcomes.
- SCM and CI own review, merge identity, and merged-revision evidence.
- Personal knowledge stores continuity, reflection, and private notes. It links durable repository material and is not a repository mirror.
- Portable configuration may name required environment variables, such as
token_env = "JIRA_API_TOKEN", but never contains their secret values. Machine configuration owns account choices and local paths; credential values stay in a keychain or secret injector and enter only the process environment.
When sources disagree, reconcile their owned facts; never overwrite one store with a copy of another.
Capability boundaries¶
Initialization and adoption may select any subset of specs, tracker,
knowledge, scm, deploy, and agent-client. Selection controls declared
roles and generated provider assets.
- Project setup, checks, architecture, design, decisions, and runbooks remain useful without external providers.
- The publish/start/finish lifecycle requires configured tracker and SCM roles; the tracker has no fallback. Omitting SCM also omits the generated GitHub workflow, so merged-revision CI completion is unavailable.
work statusinspects the local record without querying the tracker.- Work that does not require a specification records
requires_spec = falsewith a reviewed reason; work that does require one configures the role. - Knowledge, deployment evidence, and agent clients are optional; deployment becomes a finish gate only when configured.
The tool map lists the default provider for each role and the compatibility fallbacks.
Start team adoption with the repository's existing development commands. Select
the capabilities and clients it needs, choose shipped skills through
agents.skills, and put acceptance and regression commands in checks.commands
and checks.required. Scaffold checks are a starting point: a new Python
project's behavior test covers only its greeting output. Replace it with the
project's real acceptance and regression suite.
For edit feedback, run ai-dlc project check --check CHECK_ID, repeating
--check for more commands; they run in the requested order. A focused receipt
still lists every configured required check, so missing required outcomes cannot
pass the completion gate. Run the full required check after target-branch
integration, before merge. The
brownfield behavior-check rehearsal
covers adopting a team's existing checks.
Daily operating loop¶
- Reconcile tracker priority, work bindings, branch state, and fresh evidence.
- Use discovery when the problem or outcome is unclear.
- Draft and review product requirements when durable rationale is needed.
- Produce the minimum design that closes product and technical ambiguity.
- Record whether formal specification is required and make it current when it is.
- Review the work record, then publish and start it through ai-dlc.
- Implement on the bound branch with acceptance and regression tests.
- Run
ai-dlc project check --requiredbefore review. - Immediately before merge, update the branch from the target branch and rerun required checks; record documentation dispositions again only for targets the gate reports stale.
- Merge through the configured SCM and finish through ai-dlc so the specification, merged revision, CI receipts and deployment evidence are checked together.
- Update durable documentation and leave a concise handoff when continuity is needed.
Completion is evidence-gated¶
ai-dlc work finish <work-id> is the completion boundary for projects with
tracker and SCM roles. It checks the authenticated merged revision rather than
the local checkout. The generated single-job GitHub workflow publishes
ai-dlc-receipt; matrix repositories declare every expected artifact in
scm.receipt_artifacts. A missing, malformed, dirty, mismatched, duplicate or
expired receipt blocks completion.
Tracker completion never substitutes for a merge, green CI, a current required specification, or configured deployment evidence. Failures remain visible and retryable instead of being converted into success.
Changing the trusted service invalidates work bindings¶
A work record pins a fingerprint per provider role, so reviewed work cannot be
retargeted at a different service without an explicit review. The SCM
fingerprint covers the [scm] settings that decide which service is trusted:
repository, target_branch and workflow.
Changing any of them drifts the
bindings on every existing record, and ai-dlc work finish refuses with
Provider binding drift until each affected record is reviewed again.
receipt_artifacts is excluded: the finish gate reads expected receipt names
from ai-dlc.toml at the merged revision, so changing the CI matrix does not
drift bindings. Every other [scm] key contributes to identity.
When a binding drifts, review the affected records and remove the drifted
binding lines so they are recomputed against the current configuration. Do not
use ai-dlc project rebind for this; it migrates a role to a different
provider. Finished records keep their historical fingerprints.
Finishing after the target branch moved¶
The specification gate reads the archived change from the working checkout. That
checkout must be exactly the pull request's merge commit with a clean
openspec/ tree. Finishing immediately after merge satisfies this from the
updated main checkout. Once the target branch advances, use the explicit helper.
ai-dlc work finish <work-id> --at-merge
The helper resolves the bound PR through the selected SCM and needs its exact
merge commit available locally. It does not fetch, archive, repair CI or change
branches. It creates an owned detached checkout at that commit and runs ordinary
finish there, leaving the caller's HEAD, index and files untouched.
--handoff FILE and --learning FILE are read relative to the caller.
The result reports completion and cleanup separately. A blocked gate remains
blocked. If changes or an ownership mismatch prevent safe removal, the checkout
is retained and the recovery locator names it; inspect it before a nonforced
git worktree remove. Retrying finish reruns its gates through the same journal.
The manual fallback remains available:
git worktree add --detach /tmp/finish-<work-id> <merge-commit>cd /tmp/finish-<work-id> && ai-dlc work finish <work-id>cd - && git worktree remove /tmp/finish-<work-id>
Take the merge commit from the pull request the work record binds; the blocked
reason also names it. The gate is unchanged: a checkout that is not exactly the
merged revision, or one with modified openspec/ files, still refuses.
When a work record is needed¶
A work record binds reviewed scope to a tracker item, a branch and a pull
request. That binding lets ai-dlc work finish close the item against the
merged revision and its CI receipts. Create one when the change delivers a
tracker item or needs a formal specification.
No required check demands a record for every change. A change with no tracker
item and no specification decision needs only its pull request: a documentation
correction, a roadmap edit, a dependency bump. Put scope and verification in the
PR body and record documentation evidence under any identifier
(--evidence-id <branch-or-topic>).
A record created for such a change has nothing to finish and stays open in the context brief indefinitely.
Projects selecting the optional bound-push hook also choose the rules for its
covered publication commands. Omitted agents.bound_push_policy, or explicit
"all-branches", requires reviewed tracker-bound work even for the record-free
PR path above. A team may explicitly choose the lighter path in shared
ai-dlc.toml:
[agents]
bound_push_policy = "tracked-branches"
This setting does not enable the hook. When the hook is selected, it allows a covered push or PR creation in two cases. Either the local inventory proves the current branch unbound, or every matching work record is valid, reviewed, tracker-bound and free of binding drift. Anything else blocks publication with a repair instruction.
Only project configuration can set this policy. The hook covers supported native tool payloads only and replaces none of the review, check or finish gates; the tool map has the details.
Merge against the current target branch¶
Documentation-impact decisions are stored per work item under
.ai-dlc/documentation/evidence/<id>.json. Each decision binds the content of
its own target and of the sources mapped to it; it does not name a target-branch
commit.
The gate computes changed files from the merge base of the CI comparison and
HEAD. A moved target branch therefore invalidates a decision only when it
changed content that the decision bound. Branches with disjoint changes merge
in either order with no evidence rewrite. Immediately before merging, do this.
- Fetch and update the branch from the target branch.
- Run
ai-dlc project check --required. Whendocs gatereports a stale target it names the paths whose content differs. Review those and record that target again withdocs review --disposition ... --evidence-id <id>, which keeps the decisions that remain valid. Missing targets need a first decision. - Push the update and wait for fresh required checks.
Pull request checks do not rerun when the target branch moves. A green check can therefore predate a target change that touched bound content; the target-branch run after merge then fails and names it.
To catch that before merge, enable the branch protection option that requires branches to be up to date, with the Verify jobs as required checks. ai-dlc does not change that setting.
Evidence files whose decisions no longer match any current target are inert;
ai-dlc docs review --base <target> --prune lists them and --apply removes
them. A project that still holds only schema 1
.ai-dlc/documentation/current.json must record that file again whenever the
target branch moves; the first per-work recording supersedes it.
Rules for editing this handbook are in CONTRIBUTING.