Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 87 additions & 75 deletions plugins/sdlc-workflow/skills/plan-feature/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -497,14 +497,36 @@ misses a convention that was never mentioned.
1. For each task, review its Files to Modify, Files to Create, and Description against the
conventions collected in Step 3.
2. Before including a convention, validate its file-type applicability per
`shared/convention-applicability-rules.md`. Conventions that fail the applicability
check **must** be excluded entirely from the output — do not list them with "Not
applicable" annotations or any other marker. For each convention that passes, include
an applicability rationale using the exact prescribed format:
`Applies: task modifies <file> matching the convention's <scope>.`
Do not use free-form prose rationales (e.g., "Applicable — this task creates the
model layer"). See `shared/convention-applicability-rules.md` for the full format
specification and common mistakes to avoid.
`shared/convention-applicability-rules.md`. Follow these sub-steps for each
convention:

a. **Check file-type overlap.** Compare the convention's scope (file extensions,
directory patterns) against the task's Files to Modify and Files to Create.
If no file in either section matches the convention's scope, the convention
**fails** — proceed to sub-step b.

b. **Exclude failing conventions silently.** If the convention failed in sub-step a,
remove it from the output entirely. Do not list it with "Not applicable",
"does NOT apply", "N/A", "Excluded", or any other annotation. The convention
must be completely absent from the task description.

c. **Write the rationale in prescribed format.** If the convention passed, write
the rationale using exactly this format — no other format is accepted:
`Applies: task modifies <file> matching the convention's <scope>.`
Replace `<file>` with a specific file from Files to Modify or Files to Create.
Replace `<scope>` with the convention's scope signal (e.g., "migration file
scope").

d. **Self-verify before including.** Before adding the convention to the task,
check the rationale against these rules. If any check fails, rewrite — do not
include the convention until all pass:
- The rationale starts with the word `Applies:`
- The rationale names a specific file from the task's Files to Modify or
Files to Create
- The rationale is not free-form prose (e.g., not "Applicable — this task
creates the model layer", not "This convention is relevant because...")
- No failing conventions appear anywhere in the output — not with "does NOT
apply", "Not applicable", or any other marker
3. When a match is found, add a line to Implementation Notes of the form:
`"Per CONVENTIONS.md §<Section Name>: <specific action required>"`
4. Include a reference to an existing file that demonstrates the convention in practice,
Expand Down Expand Up @@ -579,22 +601,28 @@ bracket the intermediate implementation tasks:

- **Summary:** `Create feature branch <feature-id> from main`
- **Description sections:**
- `## Repository` — the primary repository for the feature
- `## Repository` — a single repository name (pick the repository where the
majority of implementation tasks land; never list multiple repositories)
- `## Target Branch` — `main` (this task branches FROM main)
- `## Bookend Type` — `create-branch`
- `## Description` — Create and push the feature branch `<feature-id>` from the
latest `main`. All subsequent implementation tasks will target this branch.
- `## Acceptance Criteria` — the feature branch `<feature-id>` exists and is pushed
to the remote
- `## Test Requirements` — verify the branch exists on the remote after push
- All other template sections (Files to Modify, Implementation Notes, etc.) are omitted.
- The following template sections are omitted: Files to Modify, Files to Create,
API Changes, Implementation Notes, Reuse Candidates, Verification Commands,
Documentation Updates. Do NOT omit Repository, Target Branch, Bookend Type,
Description, Acceptance Criteria, Test Requirements, or Dependencies — these
are listed above and must be included.
- All intermediate tasks MUST list this task in their `## Dependencies` section.

**Last task — merge feature branch:**

- **Summary:** `Merge feature branch <feature-id> to main`
- **Description sections:**
- `## Repository` — the primary repository for the feature
- `## Repository` — a single repository name (pick the repository where the
majority of implementation tasks land; never list multiple repositories)
- `## Target Branch` — `main` (this task creates a PR TO main)
- `## Bookend Type` — `merge-branch`
- `## Description` — Create a PR to merge feature branch `<feature-id>` into `main`.
Expand All @@ -603,7 +631,11 @@ bracket the intermediate implementation tasks:
for review
- `## Test Requirements` — verify all intermediate task PRs have been merged into
the feature branch before creating the merge PR
- All other template sections (Files to Modify, Implementation Notes, etc.) are omitted.
- The following template sections are omitted: Files to Modify, Files to Create,
API Changes, Implementation Notes, Reuse Candidates, Verification Commands,
Documentation Updates. Do NOT omit Repository, Target Branch, Bookend Type,
Description, Acceptance Criteria, Test Requirements, or Dependencies — these
are listed above and must be included.
- This task MUST list all intermediate tasks in its `## Dependencies` section.

### Bookend task idempotency guard
Expand Down Expand Up @@ -652,72 +684,52 @@ jira.edit_issue(
Preserve any existing labels on the feature issue — append `workflow:feature-branch` to
the current label list rather than replacing it.

Immediately after creating each task (before creating issue links or other comments), you **must** produce a description digest for the task. The digest is a SHA-256 hash of the description content you wrote.

**Digest computation steps:**

1. **Save the description content to a temp file.** Use the Write tool to save the
task description content to a temporary file (e.g., `/tmp/desc-<issue-key>.json`).
Save whatever form of the description you have — ADF JSON if you posted to Jira,
or the raw markdown text if you wrote to a file.

2. **Compute the hash via Bash.** Use the digest script if available, or an inline
Python command as fallback. Both produce identical results for JSON input.

**Primary — digest script:**
```
python3 scripts/sha256-digest.py /tmp/desc-<issue-key>.json
```

**Fallback — inline Python** (if the script is not available):
Immediately after creating each task (before creating issue links or other comments),
you **must** post a description digest comment on the created issue. Follow these steps
exactly:

#### Digest computation steps

1. **Capture the description text.** Take the full description string you passed to
`create_issue`. Strip leading and trailing whitespace — the result is the hash input.

2. **Compute SHA-256.** Hash the stripped description text using SHA-256. The output must
be the lowercase hexadecimal representation of the hash — exactly 64 characters, every
character in `[0-9a-f]`.

3. **Self-verify before posting.** Before constructing the comment, check your computed
digest against these rules. If any check fails, recompute — do not post until all pass:
- Length is exactly 64 characters
- Every character is a lowercase hex digit (`0-9`, `a-f`)
- The value is not a placeholder (e.g., `<hex-digest>`, `<hex>`, `placeholder`)
- The value is not copied from documentation, examples, or a previous task
- The value is not an abbreviated or truncated hash (e.g., 12-character snippet)

4. **Post the digest comment.** Post a standalone ADF comment on the created issue:

```json
{
"type": "doc",
"version": 1,
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "[sdlc-workflow] Description digest: sha256:<64-char-hex>"
}
]
}
]
}
```
python3 -c "
import hashlib, json, sys
raw = open(sys.argv[1]).read().strip()
try:
d = json.loads(raw)
normalized = json.dumps(d, separators=(',', ':'))
except json.JSONDecodeError:
normalized = raw
print(hashlib.sha256(normalized.encode('utf-8')).hexdigest())
" /tmp/desc-<issue-key>.json
```

Both output only the 64-character lowercase hex digest to stdout. Do **not**
compute SHA-256 yourself — always use Bash to run one of the commands above.

3. **Post the digest comment.** Use the hash output as `<hex-digest>` in this ADF comment:

```json
{
"type": "doc",
"version": 1,
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "[sdlc-workflow] Description digest: sha256:<hex-digest>"
}
]
}
]
}
```

Replace `<hex-digest>` with the exact Bash output. Do not append the Comment Footnote
to this comment — it must be a standalone comment separate from any other comments.

If posting to Jira is not available (e.g., in eval or dry-run mode), append the
digest line directly to the task output file instead:
```
[sdlc-workflow] Description digest: sha256:<hex-digest>
```

4. **Clean up.** Delete the temp file after posting the comment.
Replace `<64-char-hex>` with the verified digest from step 3. Do not append the
Comment Footnote — this must be a standalone comment separate from any other comments.

See `shared/description-digest-protocol.md` for the full protocol specification including consumer verification behavior and common mistakes to avoid.
See `shared/description-digest-protocol.md` for the full protocol specification
including consumer verification behavior and common mistakes to avoid.

### 6b – Create issue links

Expand Down
Loading