Skip to content

T-XSI8-task-define-flags-spec-shell-drift

Status: closed/superseded · Impact: low · Complexity: small

Auto-generated from a /sdlc:task-work post-mortem. Review and promote to open/ready before picking up.

A task spec frequently cites shell invocations of a target skill (“/sdlc:pr-check calls gh pr view and gh api .../comments”) as evidence of “Today” behaviour, but the cited SKILL.md may have moved on between when the spec was authored and when an implementer picks it up. Surfaced during T-BM56-pr-check-mock-state-flag: the spec described /sdlc:pr-check as making two gh calls when the live SKILL.md had already collapsed comments and reviews into a single gh pr view --json …,comments,reviews fetch. The drift was benign here (the underlying intent — “swap the live gh payload for a JSON blob” — still applied), but a tighter check at pickup would catch the larger class of “spec describes a code shape that no longer exists” before implementation effort is sunk.

From the originating post-mortem’s Friction list:

The task spec mentions gh api .../comments as a separate call the skill makes, but the live SKILL.md already collapses comments and reviews into the single gh pr view --json …,comments,reviews fetch. Spec was authored against a prior shape of the skill — a task-spec “still accurate?” check at pickup that diffs cited shell invocations against current SKILL.md would catch this class of drift before implementation starts.

/sdlc:task-ensure-ready today validates referenced file paths (see T-V8K4-task-ensure-ready-fuzzy-locates-cited-paths) but does not extract or verify shell invocation patterns the spec attributes to other skills. A task that says “pr-check calls gh foo bar” passes the readiness gate even when the referenced skill never makes that call.

Per the PR #88 review feedback (captured at the bottom of this file), the right shape is a resolver interface rather than a hardcoded SKILL.md grep:

  • /sdlc:task-ensure-ready extracts cited shell command patterns from the task body (regex-driven; covers <skill> calls \`, ``.*against the real `, and similar shapes surfaced by a quick survey of recent task specs).
  • For each extracted pattern, the check delegates to a resolver that knows how to verify the cited invocation against the cited target. Resolvers ship as small adapters: a default SkillMarkdownResolver greps the cited SKILL.md; consumer projects can register their own resolvers (kubectl apply → deploy script, pnpm run Xpackage.json, etc.) via sdlc.yaml.
  • For the upstream SDLC plugin specifically, the SKILL.md-grep resolver lives behind the project-local skill extension convention (plugin/conventions/project-local-skill-extension.md) so the hard-coded coupling never enters the upstream skill. The skill loads .sdlc/skill-ext/task-ensure-ready/cited-invocations.sh (or .py) as the extension point; the SDLC repo ships a SkillMarkdownResolver adapter at that path; consumer repos can ship their own.
  • Mismatches surface as an advisory note on the readiness verdict rather than a hard fail — the drift is often benign, but the human should know.
  1. Survey: read 3-5 recent task specs and identify the actual syntactic patterns authors use to cite shell invocations of other skills. The extractor’s regex is only useful if it covers the common case.
  2. Define the resolver contract — input shape (cited command + cited target file), output shape (OK / MISMATCH: <reason> / SKIP: <reason> for unknown target types), and how sdlc.yaml registers additional resolvers.
  3. Ship the SkillMarkdownResolver default in this repo via the project-local skill extension convention: under .sdlc/skill-ext/task-ensure-ready/ (consult plugin/conventions/project-local-skill-extension.md for the exact event/script-name shape).
  4. Wire the extractor + resolver invocation into /sdlc:task-ensure-ready as a non-blocking advisory. Print a note: line under the readiness verdict pointing at the mismatched invocation and the resolver’s diagnostic. Do not downshift status.
  5. Document the resolver contract in plugin/entities/task/implementation-ready.md as an advisory layer — failing it does not flip the verdict, only annotates it.
  6. When this task is re-picked up, reconcile against 2026-05-22-task-ensure-ready-generalize-beyond-skill-md — the generalization captured there should drive the resolver contract’s shape.
LocationKindChange
plugin/skills/task-ensure-ready/SKILL.mdmodifydocument the cited-invocation extractor + resolver-delegation step (non-blocking advisory).
plugin/entities/task/implementation-ready.mdmodifynote the resolver contract as an advisory layer; failing it does not flip the verdict.
plugin/skills/task-ensure-ready/cited_invocations.pynewextractor + resolver-dispatch helper invoked from the skill.
.sdlc/skill-ext/task-ensure-ready/cited-invocations.shnewthis repo’s SkillMarkdownResolver shipped via the project-local extension convention.
plugin/conventions/sdlc-yaml.mdmodifydocument the resolver-registration shape under sdlc.yaml.
  • AC-1: A task spec that cites \gh api …/comments`against a skill whose live SKILL.md never references that string surfaces an advisory note from/sdlc:task-ensure-ready(or/sdlc:task-define) — the run still emits READY:` (the check is non-blocking), but the note appears in the skill’s stdout.
  • AC-2: A task spec whose cited invocations all match the live SKILL.md emits no advisory note. (No false positives on healthy specs.)
  • AC-3: The check is documented in plugin/entities/task/implementation-ready.md as an advisory layer — failing it does not flip the verdict, only annotates it.
  • Auto-fixing the drift. The human author decides whether the spec or the skill is the source of truth.
  • Generalizing this to non-shell drift (e.g. referenced symbol names). That’s the existing T-V8K4-task-ensure-ready-fuzzy-locates-cited-paths pattern; this task is specifically about shell-invocation lines.
  • none

Spawned by /sdlc:task-work post-mortem of T-BM56-pr-check-mock-state-flag on 2026-05-21.

Review feedback (from PR #88, closed for refactor)

Section titled “Review feedback (from PR #88, closed for refactor)”

Reviewer (sksizer) flagged a scope/architecture concern on the spawned follow-up task 2026-05-21-cited-invocations-extends-to-py-scripts.md that applies equally to this parent task:

  • The cited-invocation check as designed is too SKILL.md-shaped. Extending the regex to *.py is a narrow patch on a check that assumes the consumer is building Claude plugins. The SDLC plugin is meant to be a generalized orchestration framework for software (hence the name), not a tool just for making itself or other Claude plugins.
  • The right shape is a resolver interface carved out of check_cited_invocations.py: ship SkillMarkdownResolver as one default, and let consumer projects register their own reference targets + verb vocabularies via sdlc.yaml (e.g. kubectl apply resolved against a deploy script, pnpm run X resolved against a package.json).
  • This means the implementation here should not just regex shell lines and grep SKILL.md — it should define the resolver contract first, then ship a SKILL.md-shaped resolver as the default implementation, with sdlc.yaml as the registration surface for consumer-specific resolvers.
  • A separate follow-up task 2026-05-22-task-ensure-ready-generalize-beyond-skill-md was drafted to capture the generalization concern. When this task is re-picked up post-refactor, reconcile against that task — the generalization is likely the actual right answer and this shell-drift check should land as a resolver, not as a hardcoded SKILL.md grep.

← Back to Tasks