T-CF7M-autonomy-gated-best-effort-auto-define
Status: closed/done · Impact: high · Complexity: large
The /sdlc:orchestrate loop parks tasks at needs-definition whenever
ensure-ready finds a spec gap, because the non-interactive dispatch can’t run
AskUserQuestion to resolve it (observed 2026-06-02: T0001/T0002/T0015 all
parked). For tasks the operator has explicitly marked high-autonomy, the agent
should instead best-effort define the spec to readiness and carry the work all
the way to a PR — never merging. This unblocks autonomous throughput on
opted-in tasks while keeping a human at the merge gate.
| Location | Role today |
|---|---|
plugin/lib/model/entities/task/schema.json | autonomy enum is human-only, supervised; the autonomous/<target> namespace is documented as reserved but undefined |
plugin/skills/task-ensure-ready/SKILL.md | on a gap, records definition_gap and downshifts to planning/needs-definition; never auto-fixes; no autonomy awareness |
plugin/skills/task-ensure-ready/ensure_ready_mutate.ts | deterministic verifier; emits ENSURE-READY-OK: / ENSURE-READY-NEEDS-DEFINITION:; never edits body content |
plugin/skills/task-define/SKILL.md | interactive (AskUserQuestion) gap-filling; no non-interactive mode |
plugin/skills/task-work/SKILL.md | Step 5a calls ensure-ready and halts on NEEDS-DEFINITION |
plugin/scripts/new_task.ts | AUTONOMY_CHOICES is ["human-only","supervised"] |
Proposed
Section titled “Proposed”autonomous/pris a validautonomyvalue meaning: the agent may best-effort self-ready and implement this task autonomously up to opening a PR, and must never merge. It is one rung abovesupervisedon the documentedautonomous/<target>ladder.- A new
/sdlc:task-auto-defineskill non-interactively brings a task to readiness with best-effort, LLM-synthesized content (the autonomous sibling of the interactive/sdlc:task-define). It flags the result as machine-authored, commits it, and never callsAskUserQuestion. - The ensure-ready skill (not its deterministic core) gains one branch:
when the verifier reports a gap AND the task’s
autonomyisautonomous/pr, it dispatches/sdlc:task-auto-define, then re-runs the verifier — stamping readiness on pass, falling back to today’sneeds-definitiondownshift on fail.ensure_ready_mutate.tsis unchanged. - Net: an
autonomous/prtask the loop picks up self-readies and proceeds to a PR instead of parking.
Approach
Section titled “Approach”- Schema + choices. Add
autonomous/prto the taskautonomyenum with semantics documented inline; mirror inbody-template.eta’s field comment and innew_task.tsAUTONOMY_CHOICES. Enum widening is backward-compatible — decide explicitly whether it warrants aschema_versionbump + migration (default: no bump; record the reasoning). - New skill
/sdlc:task-auto-define. Reuse task-define’s gap detection; replace theAskUserQuestionelicitation with best-effort synthesis from the task’s existing prose + codebase context. Emit slug-namespaced terminal markers (TASK-AUTO-DEFINE-DEFINED:/-NO-CHANGES:/-INSUFFICIENT:). Stamp a discoverable “spec auto-defined — review carefully” marker on the result. Commit per the commit-message convention. - ensure-ready skill branch. After the deterministic verify reports
NEEDS-DEFINITION, read the task’sautonomy; ifautonomous/pr, dispatch/sdlc:task-auto-define(one attempt), then re-run the verifier. OnOK→ stamp + emitENSURE-READY-OK:(noting auto-defined); on still-failing → the existing downshift. Keepensure_ready_mutate.tspure. - Loop guard. Exactly one auto-define attempt per ensure-ready run; if the re-verify still fails, park (no retry storm with a deterministically-failing definer).
- Tests. Schema accepts/round-trips
autonomous/prand still rejects unknown values;task-auto-definefills a fixture gap with zeroAskUserQuestioncalls; ensure-ready auto-defines+passes forautonomous/prand parks forsupervised/human-only/absent. - Docs. Per-skill doc
docs/skills/task-auto-define.md; note the tier in task-work + orchestrate; follow the per-skill-doc house-style.
Files to touch
Section titled “Files to touch”| Location | Kind | Change |
|---|---|---|
plugin/lib/model/entities/task/schema.json | modify | add autonomous/pr to the autonomy enum + doc |
plugin/lib/model/entities/task/body-template.eta | modify | document autonomous/pr in the autonomy field comment |
plugin/scripts/new_task.ts | modify | add autonomous/pr to AUTONOMY_CHOICES |
plugin/skills/task-auto-define/SKILL.md | new | non-interactive best-effort define skill |
plugin/skills/task-ensure-ready/SKILL.md | modify | autonomy-gated auto-define dispatch + re-verify branch |
plugin/skills/task-work/SKILL.md | modify | note autonomous/pr self-ready behavior at Step 5a |
plugin/skills/orchestrate/SKILL.md | modify | note autonomous/pr tasks self-ready rather than park |
docs/skills/task-auto-define.md | new | per-skill doc (Mermaid flowchart) |
Acceptance criteria
Section titled “Acceptance criteria”- AC-1: frontmatter validation accepts a task with
autonomy: autonomous/prand rejects an unknown autonomy value (test). - AC-2:
/sdlc:task-auto-define <slug>run against a fixture task with a fillable gap produces a spec that/sdlc:task-ensure-readythen passes, and it issues zeroAskUserQuestioncalls (test). - AC-3: with a gap present, the ensure-ready skill auto-defines + re-verifies to
ENSURE-READY-OK:whenautonomy: autonomous/pr, and parks atplanning/needs-definitionwhen autonomy issupervised/human-only/ absent (test). - AC-4: an auto-defined spec carries a discoverable machine-authored marker, and no flow introduced by this change ever merges a PR.
- AC-5:
ensure_ready_mutate.ts’s contract is unchanged — same markers, still never edits body content (its existing tests pass untouched).
Out of scope
Section titled “Out of scope”- The
autonomous/mergeandautonomous/releaseladder rungs (future). - The mechanical-vs-semantic NEEDS-DEFINITION classification of T-IW1W-needs-definition-auto-fix-vs-human-triage (a different axis; may be superseded by or composed with this task — operator’s call).
- Auto-merging or any post-PR automation.
Dependencies
Section titled “Dependencies”- none
Discovery context
Section titled “Discovery context”Designed interactively on 2026-06-02 after the /sdlc:orchestrate loop parked
T0001/T0002/T0015 at needs-definition — the non-interactive dispatch can’t
run AskUserQuestion, so spec gaps a human would resolve in seconds become
dead-stops. The autonomous/pr name (matching the schema’s reserved ladder),
its “best-effort to a PR, never merge” semantics, and the “its own skill”
shape were agreed in that session. Relates to the earlier undefined stub
T-IW1W-needs-definition-auto-fix-vs-human-triage.
Post-mortem
Section titled “Post-mortem”Captured by /sdlc:task-work on 2026-06-02. PR: pending.
Acceptance criteria coverage
Section titled “Acceptance criteria coverage”- AC-1: auto —
task_autonomy_enum.test.ts+new_task.test.ts(schema acceptsautonomous/pr, rejects unknown values). - AC-2: auto —
task_auto_define.test.ts(auto-defined fixture spec +AUTO-DEFINED:marker passes the real ensure-ready verifiers toENSURE-READY-OK:; non-interactive contract enforced byAskUserQuestion’s absence fromallowed-tools). - AC-3: auto —
ensure_ready.test.ts(gate auto-defines forautonomous/pr, parks forsupervised/human-only/absent; core fail-mutation stays autonomy-agnostic). - AC-4: auto/agent-manual — never-merge boundary asserted in skill prose (task-auto-define,
task-work, orchestrate); the discoverable
AUTO-DEFINED:marker verified to survive end-to-end. - AC-5: auto —
ensure_ready_mutate.tsunmodified; its existing tests pass untouched.
What worked
Section titled “What worked”- The spec’s files-to-touch table and ACs mapped cleanly to the implementation; ensure-ready’s pure-verifier boundary made the skill-level autonomy branch a localized, low-risk change.
- Skill directory auto-discovery (
"skills": "./skills"in the plugin manifest) meant the new skill needed no manifest/index registration.
Friction and automation gaps
Section titled “Friction and automation gaps”- Step 7’s baseline-diff gate reported
FAIL new-drift=15, but every flagged “finding” was non-deterministicbun testoutput (per-run temp-dir paths like/tmp/.../append-pr-url-*/and fixture commit SHAs), not real drift — the baseline gate is unusable againstbun testuntil its output is normalized. Already in flight as2026-05-25-normalize-baseline-diff-nondeterministic-output(PR #214). →2026-06-02-normalize-baseline-diff-nondeterministic-output bun testalways reports 4 failures (stale validator-golden fixtures for deletedepics/E0001.md,E0002.md,decisions/model-entities.md, plus an edited task fixture), masking the real signal regardless of the change under test. Already in flight as the stale-fixture pruning in PR #221.check_skill_docsshows 4 pre-existing per-skill docs missing on main (pr-respond, spawn-task-pr, standard-new, migrate-runtime-state) — pre-existing coverage drift, not touched here. → T-OH4Y-write-missing-per-skill-docs
Spawned follow-up tasks
Section titled “Spawned follow-up tasks”- T-OH4Y-write-missing-per-skill-docs (https://github.com/sksizer/dev/pull/230) — Upstream-plugin, spawned: write the four missing per-skill docs.
2026-06-02-normalize-baseline-diff-nondeterministic-output(https://github.com/sksizer/dev/pull/214) — linked to existing in-flight PR (baseline-diff nondeterministicbun testoutput); no new task spawned.- PR #221 (stale validator-golden fixture pruning) — linked to existing in-flight PR (bullet 2);
tracked as commit
dd1ce54, no standalone task file, no new task spawned.