Dependency workflows
Use Todo for genuine software dependency waiting and preserve existing PR phases.
Human action
Finish independent technical work and authorized fallbacks first. If a person
must make a product decision or perform a physical action, record a concrete
human_action in the Workpad detent-status block with status: blocked.
Detent routes the card to Blocked, where the board shows "Needs you". Keep any
existing PR intact. A reply authorizes only what it says; retain separate
authorization for sends, publishing, deployment, charges, and destructive
actions. Instance and infrastructure failures stay attributed to the instance.
Do not create synthetic human-prerequisite issues, labels, or dependency edges. Intentional standalone human tasks remain non-executable.
When the action is done, an authorized project member records what was decided
or done in a newer ## Codex Workpad comment on the original issue. Clear
human_action in its structured block. If no other blocker remains, use:
schema: 1
status: in_progress
blockers: []
human_action: null
Detent recognizes an authorized Workpad update made after the Blocked entry and moves the issue through its existing recorded-blocker recovery to Todo or Rework. An ordinary reply alone does not clear the Workpad. If other blockers remain, keep them in the newer blocked Workpad; Detent retains their normal dependency or predicate checks. Do not move the tracker lane by hand.
Convert an older generated question prerequisite
An upgrade can leave a generated detent-human issue linked to executable
work. The removed question-migration endpoint cannot convert it. For each
affected dependent, first inspect the generated source and confirm that it is
an unresolved generated question, not a software dependency or an intentional
standalone human task. Record the unresolved decision as a concrete blocked
Workpad human_action on the dependent, preserving unrelated blockers and its
PR. Then remove the generated source from the dependent's Depends on: or
Blocked by: line and from any native tracker dependency relation. Detent
keeps the dependent in Blocked with "Needs you" until the action is cleared as
above. Repeat for every dependent before retiring the generated source as not
planned, with a link to the dependents; retain the source and its comments as
history. Already completed dependents stay completed. Never treat closing the
source as approval of the decision or permission for an external action.
Dependency configuration
Workpad blockers may declare live evidence directly. Each typed blocker names
an owner, a predicate, and a recheck_interval or expires_at. Detent
re-evaluates these records on every blocked-lane tick and clears the park when
all predicates are false. The supported predicate types are issue_state,
pull_request_state, check_presence, budget_capacity, and
config_fingerprint.
schema: 1
status: blocked
blockers:
- ref: "owner/repo#123"
reason: "waiting for the dependency to close"
owner: orchestrator
predicate:
type: issue_state
states: [open]
recheck_interval: tick
human_action: null
Free-text blocker entries remain valid for compatibility, but Detent marks them unverifiable, surfaces their owner and age, and never clears them automatically. An expired predicate that still holds is also unverifiable; orchestrator-owned unverifiable parks are escalated for operator attention.
- Keep the issue in
Todo. Record the dependency as a Hub dependency relation withdetent hub issue dependencyorPOST /api/v1/work-items/{id}/dependencies. The Hub offersTodowork to runners only when it is dependency-ready; a resolved dependency has a terminal workflow state.require_dependenciesdefaults to true; setting it false disables that readiness gating for the project. This is the default behavior and needs no extra configuration. Detent also reads a machine-readable dependency line such asDepends on: #123orBlocked by: owner/repo#123in the issue description. Declarations read only the leading comma/and-separated reference list (legacy semicolon separators also work). The first sentence terminator (.,!, or?), other prose, or the end of the line ends the declaration. Periods inside repository names and URLs remain part of the reference.none,n/a, and-explicitly declare no dependencies, even when issue references follow. For example,Depends on: none. Order: #2, #3declares no blockers, whileDepends on: #2 and #3 — see #9 for contextdeclares only #2 and #3. The same rules apply toBlocked by:. - Legacy dependency waiting in
Blocked. Enabletracker.dependency_auto_unblockwhen your team wants dependency-waiting issues to sit in a waiting column. Detent only moves issues that have explicitDepends on:orBlocked by:references. When all blockers are terminal, closed, or have a merged linked PR under the configuredreadinessrule, Detent moves the issue totarget_stateand posts an audit comment. Withouttracker.dependency_auto_unblock.enabled: true, aBlockedissue is observed for display but will not be moved back toTodo. Human blockers without explicit dependency references stay blocked. - Queue fixable blockers automatically. Enable
tracker.blocker_auto_promotealongside dependency auto-unblock when a dependency-waiting issue should pull same-repository blockers out of inactive states such asBacklog,Blocked, orHuman Review. Detent promotes only resolved, same-repository blockers to the configuredtarget_state, respects current local agent capacity, and posts an audit comment on the promoted blocker. Agents that move work toBlockedbecause of another tracked issue or pull request must ensure the issue body contains a machine-readableBlocked by:orDepends on:line; Workpad mentions alone are not a durable dependency contract. - Recover explicit PR-maintenance parks. Enable
tracker.blocked_recoveryonly when structured PR-maintenance parks should move work to the configured repair lane. The worker that intentionally creates such a park must setreason_code: merge_conflict,stale_base, ormissing_current_head_ciin its blockeddetent-statusblock; Detent persists that code on the lane entry. Recovery also requires the corresponding PR condition to still hold and a new diff-fingerprint/base-OID pair. Issue descriptions, manual status moves, and other prose do not authorize recovery. Keep this disabled on boards whereBlockedis also used for deliberate operator parking.
If a runner runs under a systemd user service, verify the service PATH
resolves every command used by project hooks and validation gates;
detent doctor checks Detent's direct dependencies, not repo-specific
bootstrap tools.
Keep systemd's default KillMode=control-group for the runner service. Detent
starts each Codex and Claude worker in its own process group without leaving the
service cgroup, so its persisted worker registry can terminate stale process
groups on shutdown or startup while systemd remains the final cleanup backstop.
Do not wrap worker commands in launchers that double-fork or explicitly move
children into another cgroup.
On shared Linux hosts, add MemoryHigh and MemoryMax to
detent.runner.service as defense in depth. Size both for the aggregate
orchestrator and worker footprint,
leave capacity for unrelated workloads, and keep MemoryMax above
MemoryHigh. For example, a 32 GiB host reserved partly for other work could
use this user-service drop-in as a starting point:
[Service]
MemoryHigh=24G
MemoryMax=28G
Create the drop-in with systemctl --user edit detent.runner.service, then run
systemctl --user daemon-reload and restart the service during an approved
maintenance window. Verify the effective values with
systemctl --user show detent.runner.service -p MemoryHigh -p MemoryMax.
These cgroup limits protect the host if Detent's per-agent RSS ceiling fails; they do not
replace the per-agent ceiling or memory, IO, and CPU pressure admission
controls.