Adopting a project
State: open/active · Genre: plan
Status: working draft, 2026-10-02. Part of the strategy hub. Part of 1.0, in milestone 9, Release basics, of the roadmap.
What a solid agent-assisted project has set up, and the wizard that sets it up. The wizard is the Adopt function of the control plane made into a walkthrough, and each of its sections is one control-plane function. An interactive mock of the wizard is at wizard-prototype.html: choices on the left, the project’s state filling in on the right. The mock is a reference until the SDF shell lands.
The frame
Section titled “The frame”- The wizard writes a project profile and holds no state. Every answer lands in a file the
loop already reads:
sdlc.yaml, the model corpus, and thesdlc/tree. Re-running the wizard is a drift report, whichsdlc config scaffoldandsdlc config explainalready make cheap. - Dry-run, plan, apply. The same idiom as
sdlc apply. The wizard shows what it would write, the person approves, it writes. It can also run on a branch in a worktree so the whole result is reviewed as one PR. - Presets are complete profiles.
solo-dogfood,oss-library,team. Each is a fully definedsdlc.yaml, an inherited pack set, and a routing table. The person starts from a preset and edits. - The person’s own repo, never a sample. A sample doubles the surface to maintain and teaches the wrong files.
Layout: the sdlc/ tree
Section titled “Layout: the sdlc/ tree”Milestone: none yet. M-KJFH is the closest: its derive step writes the step directories.
Proposed default for new projects. The committed, sdlc-owned tree is one directory, and the corpus moves under it under the name of the control-plane function it serves.
sdlc.yaml # stays at the root: tools discover a project by itsdlc/ model/ # the corpus (today docs/planning/): products, capabilities, ... workflows/<name>/ # a workflow defined as a directory of ordered steps hooks/<git-hook>/ # git hooks, same step files extend/<skill>/<point>/ # skill lifecycle extensions, same step files journal/ # optional committed journal shards (see The operational record).sdlc/ # runtime state, gitignored, per machinepaths.model roots the corpus elsewhere for a project that wants it under docs/. The OKF
bundle root follows the corpus root, so the bundle settled as docs/ moves with it. This repo
keeps docs/planning/ through that key until it migrates. sdlc/ next to .sdlc/ reads as
committed intent beside ignored runtime state.
Steps, in order
Section titled “Steps, in order”Milestone: M-KJFH.
- Install and check. Plugin and binary present,
sdlc project doctorclean. - Adopt the repo.
sdlc init, a validsdlc.yaml, the control-plane ref, trust, register with SDF. One roster, with the other as its projection. - Inherit packs. Pick the dev packs, the inherit mode, and preview what each pack turns on.
- Model a first slice. A product, two or three capabilities groomed with
capability-groom, one decision. - Checks. Detect runners, compose
checkandsetup, arm hooks, runcheckonce, capture the first baseline, then run a judge calibration. - Routing. Probe hosts and harnesses, accept or edit the profile table and routing table.
- Autonomy and steering. Pick the posture, a channel, the events, the budget.
- Plan. A milestone with tasks that meet the readiness contract.
- Run one task by hand.
task-workto a PR, then review and respond. - Turn on the loop. Opt one PR in with the
sdlc:orchestratelabel, watch the plan in dry run, then live. Pause, resume, read the tick log, open SDF and the TUI. - Extend and record. Drop a first file into
sdlc/extend/, open the run summary of the task from step 9.
Each step checks the previous one before moving on, and can be resumed later. Surfaces: an
sdlc skill, onboard, that walks the steps in a session, and the same steps as a page in SDF
and the TUI from the shared console view models.
The eleven dimensions
Section titled “The eleven dimensions”1. Identity and adoption
Section titled “1. Identity and adoption”Milestone: M-KJFH.
Built: doctor, init, sdlc.yaml, the control-plane ref, lease authority, sdlc repo trust, SDF
registration. Open: two rosters (SDF’s fleet and the planned projects: key). The wizard
picks one as source.
2. Ontology, inherited from dev packs
Section titled “2. Ontology, inherited from dev packs”Milestone: M-KJFH.
Nothing ships a starter corpus today. The published principles and the standards in this repo, including the review rubric and the response policy, are what a new project wants on day one.
A dev pack is more than entities. It carries everything a kind of project needs from this
system: principles, standards with applies_to and an enforcement level, terms, workflow
leaves, hooks, lifecycle extensions, profile defaults, and judge calibration fixtures.
| Pack | Entities | Workflows and hooks | Extensions and profiles |
|---|---|---|---|
base | The published principles, markdown formatting, the review rubric, the response policy, core terms. | check composed from fmt-check, lint, typecheck, test leaves; pre-commit running check with on_fail: park. | retro after implement and close-out; default profiles. |
typescript | Typed errors, lockfile committed, tests colocated, no raw spawns outside a seam. | Runner leaves from quality detect for node-scripts (npm, pnpm, yarn, bun), and moon with exec detection on; tsc --noEmit. | A fast verify mode on changed hunks. |
rust | No unwrap in library code, a capability per feature flag, clippy -D warnings as a standard. | cargo fmt --check, clippy, cargo test. | A longer check timeout. |
oss-library | Semver, changelog, public API review, fork PRs untrusted. | release-prepare; pre-push tag check. | pr_review.untrusted: skip-init; a review profile on the cheaper model. |
sdlc | This repo’s own conventions, for dogfooding. | This repo’s check. | Everything this repo has in sdlc/extend/. |
Inherit modes, per pack or per entity:
| Mode | What happens | When |
|---|---|---|
copy | The entity is forked into the model corpus, editable, with a drift report against the pack version. | Default, so a new project sees where things go and how they are written. |
link | Referenced by ID and pack version, rendered in the docs index, not copied. Upgrades flow. | A project that wants the pack’s rules unchanged. |
extend | Linked, plus a local file that tightens or scopes it. | Narrowing applies_to, adding a rule. |
An override is itself an entity: a local standard carries supersedes: S-0017“ or narrows
applies_to.paths. No hidden override table. Pack upgrades are the first real compatibility
surface and touch the 1.0 promise.
3. Deterministic checks: workflows, hooks and the chain
Section titled “3. Deterministic checks: workflows, hooks and the chain”Milestone: M-0M28.
Built: detection, leaves composed into check by reference, baseline-gated mode, git hooks with
when and on_fail, stage overrides on the chain. The wizard sequences it: detect, confirm
leaves, compose check and setup, arm hooks through sdlc apply, run check once, capture
the baseline.
Drop-in steps. A workflow, a hook, or an extension point can also be a directory of step files, ordered by name the way web frameworks route by file path:
sdlc/workflows/check/ 10-fmt-check.sh 20-lint.sh 30-typecheck.run # one line: the name of a workflow to splice in 40-review-notes.md # a prompt step, run under a profile| Extension | Step kind | Header |
|---|---|---|
.sh | Script, run through the shell in the checkout root. | # sdlc: on_fail=park when=deps-missing on the first lines. |
.md | Prompt or skill step, launched as a session. Never valid under hooks/. | Frontmatter: profile, on_fail, skill. |
.run | Splices another workflow’s resolved steps, cycle-checked. | The file holds one workflow name. |
The numeric prefix orders. The rest of the name is the step’s name in the journal and in
notifications. A name defined both in sdlc.yaml and as a directory is an error, never a
merge. sdlc config explain renders provenance across both forms.
4. Judgement checks
Section titled “4. Judgement checks”Milestone: M-0M28.
Built: sdlc verify changes judges a diff against every standard whose applies_to.paths
encloses a changed file, plus CLAUDE.md and AGENTS.md, and the judge stage runs it
blocking.
Enforcement per standard. Today blocking and severity_floor are one global setting on
the verify: block, so every matching standard is enforced the same way. The proposal is a
field on the standard entity:
enforcement: blocking # blocking | advisory | offseverity_floor: tension # violation | tension | drift: the lowest severity that countsblocking fails the judge stage and the hook that runs it. advisory posts the finding and
passes. off keeps the standard as documentation only. The field sits next to the text it
governs, and a copy-inherited standard is the project’s own file, so the project tunes it
there. sdlc.yaml and the machine file may override by ID for one checkout.
Verify modes. The verify verb grows named modes so the same rules run at the right cost in
the right place:
| Mode | Scope | Profile | Where |
|---|---|---|---|
fast | Changed hunks, blocking standards only. | mechanical | pre-commit |
complete | The whole diff, every matching standard. | judge | pre-pr, the judge stage |
review | Adversarial read with the rubric. | review | The review stage |
Calibration run. Before blocking is on, judge the last ten merged PRs with the chosen
standards and show the findings beside what reviewers actually said. The person sees the
false-positive rate and tunes severity_floor or demotes a standard to advisory. The
calibration reads the journal (dimension 10) once it exists.
The additive rule, stated once. A standard is a judgement rule. A workflow step is a deterministic rule. A hook, a stage binding or an extension point says when each runs. Adding a check is adding one file or one list entry, and no skill is edited.
5. Hook points and overrides
Section titled “5. Hook points and overrides”Milestone: M-0M28.
Four mechanisms exist: git hooks:, chain stages.<name>.workflow, pr_review.prompt
extend or replace, and skill extensions (the .lifecycle file in
Skill lifecycle extensions, plus the older
.sdlc/skill-ext/<slug>/<event>.sh convention). They should read as one system:
- One vocabulary of points:
before,after,rules,after-<step>.rulesholds.mdonly.replaceexists only where a skill declares a step replaceable. This settles the open question in the extensions page toward a fixed vocabulary. - One file shape: the drop-in steps of dimension 3, under
sdlc/extend/<skill>/<point>/. Directories supersede the single.lifecyclefile, which revisits the row settled on 2026-10-02. A skill with chain-stage hooks uses the stage’s bound workflow as the target. - One listing:
sdlc extend listprints every point every installed skill declares, filled or unfilled for this project. The wizard walks it and scaffolds the directories with a commented example step in each. - One explanation:
sdlc config explaincovers extensions, so one command answers what runs at a point and who put it there.
6. Hosts, harnesses and models by kind of work
Section titled “6. Hosts, harnesses and models by kind of work”Milestone: M-EG9L.
Built: engine and host per workflow name; verify engine, model and timeout set once and
overridable per subtree by a nested sdlc.yaml; headless workflow dispatch limited to claude and
codex (verify.engine also takes gemini and opencode); no fallback across hosts. Missing: the
routing layer.
Profiles are named by kind of work, never by model:
profiles: mechanical: { engine: claude, model: haiku, effort: low, headless: true } design: { engine: claude, model: sonnet, effort: medium, headless: true } review: { engine: codex, model: default, effort: high, headless: true } judge: { engine: claude, model: haiku, effort: low, headless: true } research: { engine: claude, model: opus, effort: high, headless: true } interactive: { engine: claude, model: default, host: tmux, headless: false }Workflows, stages and .md steps reference a profile instead of carrying engine and host.
The routing table maps task attributes to a profile: complexity × autonomy × stage.
routing: default: design rules: - { stage: implement, complexity: small, autonomy: autonomous/pr, profile: mechanical } - { stage: implement, complexity: large, profile: design } - { stage: judge, profile: judge } - { stage: review, profile: review }The first matching rule wins. Both tables live in sdlc.yaml as project intent. The machine
file and sdlc.local.yaml override bindings per key, because which models and hosts exist is a
fact about a machine. The wizard probes harnessAvailable and the host binaries and proposes
bindings. A profile whose engine is missing fails with a named reason, consistent with the host
contract.
7. Autonomy posture
Section titled “7. Autonomy posture”Milestone: M-0M28.
Policy is spread across the task autonomy field, sdlc:auto/<stage> labels, orchestrator
limits, max_rounds, trust and the usage budget. The wizard presents it as one dial and shows
which keys and labels each position sets:
| Posture | Ceiling | What it sets |
|---|---|---|
observe | auto/triage | Dry-run ticks, no dispatch, notifications on. |
supervised | auto/implement | Dispatch to a PR, review by a person, max_rounds: 1. |
autonomous-to-pr | auto/respond | Review and respond rounds unattended, max_rounds: 3, budget set. |
Autonomy-to-stage is the one nomenclature. The task field becomes autonomy: to/<stage>,
mirrored by the sdlc:auto/<stage> label, with the posture as the project default and a task
able to lower it. A person at the merge stays fixed in every posture.
8. Steering and notifications
Section titled “8. Steering and notifications”Milestone: M-EG9L.
Built. Three channel shapes and ten events:
| Channel type | Fields |
|---|---|
desktop | None. A notification on the machine running the loop. |
ntfy | topic_url. |
webhook | url, format (slack, discord, raw). |
| Event | Fires when |
|---|---|
pr.needs_response | A NEEDS-RESPONSE PR has exhausted orchestrator.review.max_rounds. Repeats every tick after that. |
pr.ci_failed | A CI-FAILED PR has exhausted max_rounds. Repeats every tick after that. |
task.parked | A hook parked a task, or a work-tick step failed outright. |
stage.ceiling_reached | An item reached its autonomy ceiling. |
phase.ready_for_review | Config only, no detector yet. |
lease.expired | A lease ran out. |
session.ended | A dispatched session exited. |
hook.blocked | A block hook step failed. |
orchestrator.dead_stop | Config only, no detector yet. |
usage.budget_exceeded | The rolling budget tripped. |
The wizard picks a channel, routes the four that matter first (task.parked, hook.blocked,
pr.ci_failed, usage.budget_exceeded), sets the budget, and runs one tick in dry run.
pr.ci_failed repeats on every tick once it starts, so the wizard pairs it with a quiet channel.
Journal events (dimension 10) are the source every detector reads, so the two config-only
events get detectors for free once the journal exists.
9. Post-mortem and self-improvement
Section titled “9. Post-mortem and self-improvement”Milestone: M-2QAE.
Built: the task.execution.spawn_from_post_mortem key in sdlc.yaml enables the procedure in
lib/model/entities/task/spawn-from-post-mortem.md, which turns friction bullets from a task’s
handoff into follow-up task PRs classified Local, Upstream-plugin or Cross-project-request. The
catalog names a retro prose skill. Process improvement is intrinsic to the system, so:
- A post-mortem is an
afterstep onimplement,respondandclose-out, filled by thebasepack with theretroskill. Every run leaves a structured record. - Friction is an entity. A
frictionkind with stage, skill, classification, evidence link into the journal, and cost. P-0010 already says capture, aggregate, act on signals. - An aggregation routine, weekly or every N runs, looks for recurrence: the same skill parked three times, the same judge finding declined five times, the same setup failure. Its output is a proposal PR, never a change: a draft standard, an extension step, or a routing rule.
- Skill grading from runs. skill-author defines grading checks. Running them against run records finds the skills that produce rework or review rounds, and closes the loop between the prose package and operations.
- A self-improvement budget, so the system never spends more on itself than on the work.
10. The operational record
Section titled “10. The operational record”Milestone: M-2QAE.
The Record function and its gap: no single run history per task or PR. Evidence is spread over
.sdlc/orchestrator-log.md, .sdlc/usage.jsonl, delivery records, the session registry, PR
cursors, park markers under <git-common-dir>/sdlc/park/, lease handoffs and handoff.md, all per
machine.
One append-only journal. Every event has the same shape, generated by sdlc in its own schema, never a harness transcript taken wholesale:
{ "ts": "...", "writer": "mbp-sk", "kind": "op.end", "subject": "T-ABCD", "source": "op:quality run", "run": "R-7Q2M", "outcome": "fail", "duration_ms": 8120, "cost": { "tokens": 0 }, "trace": null }Kinds: op.start and op.end with exit code, step.* for every workflow and hook step,
dispatch.* and router.*, lease.*, judge.finding, review.round, session.*,
usage.sample, friction.recorded. Logging happens during operations, not only after.
One API. sdlc journal append is the common write path. Ops emit start and end
automatically from the op runner, one instrumentation point. Skills and agents call the command.
Disk is the fallback when the CLI is unavailable, never the primary path.
Shards per writer. Raw journal files are .sdlc/journal/<writer>/<yyyy-mm>.jsonl, one
writer per file, so machines never conflict. A project that wants history in the repo publishes
shards under sdlc/journal/ through ordinary PRs, or to refs/sdlc/journal/<writer> once
multi-machine lands (milestone 11). Transcripts stay by reference: harness, session ID, path.
Run summaries. A run entity, R-XXXX, per large operation such as working a task or
responding to a review: a deterministic skeleton from the journal (timeline, stages, durations,
cost, PRs, verdicts, friction) with a short narrative section an LLM writes. It is one link from
a PR body, and from a Jira ticket when that is supported.
Consent, secrets, retention. Raw journals stay gitignored. A deterministic redaction step
runs before any transcript excerpt or summary leaves .sdlc/. Raw shards expire after N days,
summaries are kept. The wizard sets all three.
Consumers: the post-mortem routine, the usage budget, the calibration run, every notify
detector, sdlc trace <task|pr|session>, and SDF’s Record panel.
11. Secure execution
Section titled “11. Secure execution”Milestone: M-GX7X.
Built: nothing in sdlc. Zoo (apps/zoo) runs agents inside managed VM sandboxes as its own
desktop app, and C-0074 names the capability: a harness never touches the operator’s machine
directly when policy says so.
The dimension is a policy plus a host. The policy says which kinds of work must run sandboxed. The host is Zoo, offered next to terminal, tmux and Orca, and it is the only kind that satisfies the policy today. Work that must be sandboxed is refused when no sandbox host is available; it never falls back to the operator’s machine.
The owner expects this section to need the most work. What Zoo exposes for starting a VM and running a harness in it is the first unknown.
Settled here
Section titled “Settled here”| Date | Decision |
|---|---|
| 2026-10-03 | Built in SDF fixture-first (RM-DO9Z, seven milestones from M-V9RR to M-2QAE), not as an HTML mock. wizard-prototype.html is retired once the shell lands. |
| 2026-10-02 | The wizard writes files after a dry run, from a preset, against the person’s own repo. |
| 2026-10-02 | Inherit mode defaults to copy. |
| 2026-10-02 | Profiles and the routing table are project intent in sdlc.yaml; the machine file overrides bindings. |
| 2026-10-02 | Autonomy is named to a stage, to/<stage>, with three posture presets. |
| 2026-10-02 | The journal is append-only, sharded per writer, written through one sdlc command, in sdlc’s own schema. |
| 2026-10-02 | friction and run become entity kinds. |
Open questions
Section titled “Open questions”- Move the corpus to
sdlc/model/by default, withpaths.modelto root it elsewhere. This repo migrates separately. - Directories of step files supersede the
.lifecyclefile. If yes, update the settled row and the extensions page. - Whether the five packs are the right first cut, and whether a pack is a vault package next to
craftandsdlcor a directory insidesdlc. - Whether
enforcementon the standard entity needs a schema bump before 1.0, or ships as part of the modular ontology milestone. - Whether a committed
sdlc/journal/is wanted at all beforerefs/sdlc/journalexists.