Skip to content
Merged
Show file tree
Hide file tree
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
28 changes: 27 additions & 1 deletion evals/implement-task/evals.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"The plan mentions using --trailer='Assisted-by: Claude Code' in the commit (constraint 2.3)",
"The plan references creating a branch named TC-9201 or notes the branch naming convention (constraint 3.1), and references the Target Branch value from the task description",
"The conventions analysis identifies at least 2 patterns from sibling code: error handling with Result<T, AppError> and .context(), and the model/service/endpoints module structure",
"The plan extracts and references the Target Branch section from the task description, identifying 'main' as the target branch"
"The plan extracts and references the Target Branch section from the task description, identifying 'main' as the target branch",
"The plan mentions checking for a description digest comment (Step 1.5) and notes that when no digest is found, it proceeds with a warning rather than blocking execution (backward compatibility per shared/description-digest-protocol.md)"
]
},
{
Expand Down Expand Up @@ -73,6 +74,31 @@
"The planned commit message follows Conventional Commits format (type(scope): description) and references TC-9205 in the footer (constraint 2.1, 2.2)",
"The plan extracts and references the Target Branch section from the task description, identifying TC-9005 as the target branch"
]
},
{
"id": 6,
"prompt": "Implement task TC-9201. The task description is in task-standard.md, the target repository structure is in repo-backend.md, and the project CLAUDE.md is in claude-md-mock.md. The Jira issue has one comment posted by a previous plan-feature run with the body: '[sdlc-workflow] Description digest: sha256:a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890'. Assume this digest MATCHES the SHA-256 hash of the current task description. The comment's created and updated timestamps are identical. Do NOT actually modify repository files or call external tools (Jira, git, Serena). Instead, write your response to outputs/digest-match.md describing how you would handle the description integrity verification in Step 1.5, and then write outputs/plan.md with the full implementation plan.",
"expected_output": "The response should describe verifying the description digest in Step 1.5: locating the digest comment by its marker string, comparing the stored hash with the computed hash of the current description, finding a match, and proceeding silently without any additional user prompt. The implementation plan should continue to Step 2 and beyond without interruption.",
"files": ["files/task-standard.md", "files/repo-backend.md", "files/claude-md-mock.md"],
"assertions": [
"The response describes locating the digest comment using the marker string '[sdlc-workflow] Description digest:' from shared/description-digest-protocol.md",
"The response describes computing a SHA-256 hash of the current description and comparing it with the stored digest",
"The response confirms the digests match and states it will proceed silently without prompting the user β€” no additional latency for the happy path",
"The response does not alert the user or pause execution due to the digest check β€” it proceeds directly to subsequent steps"
]
},
{
"id": 7,
"prompt": "Implement task TC-9201. The task description is in task-standard.md, the target repository structure is in repo-backend.md, and the project CLAUDE.md is in claude-md-mock.md. The Jira issue has one comment posted by a previous plan-feature run with the body: '[sdlc-workflow] Description digest: sha256:0000000000000000000000000000000000000000000000000000000000000000'. Assume this digest does NOT match the SHA-256 hash of the current task description β€” the description was modified after plan-feature created it. The comment's created and updated timestamps are identical. Do NOT actually modify repository files or call external tools (Jira, git, Serena). Instead, write your response to outputs/digest-mismatch.md describing how you would handle the description integrity verification in Step 1.5.",
"expected_output": "The response should describe detecting a digest mismatch in Step 1.5: the stored hash does not match the computed hash of the current description. The skill should alert the user that the description was modified since plan-feature created the task, display the expected vs actual digest values, and pause execution β€” asking the user whether to proceed with the current description or stop to re-run plan-feature. The skill should NOT proceed to Step 2 or beyond without the user's explicit decision.",
"files": ["files/task-standard.md", "files/repo-backend.md", "files/claude-md-mock.md"],
"assertions": [
"The response describes locating the digest comment using the marker string '[sdlc-workflow] Description digest:' from shared/description-digest-protocol.md",
"The response describes detecting a mismatch between the stored digest and the computed SHA-256 hash of the current description",
"The response alerts the user that the description was modified after plan-feature created the task and displays the expected vs actual digest values",
"The response offers the user a choice: (1) proceed with the current description, or (2) stop so they can re-run plan-feature",
"The response stops execution and does not proceed to Step 2 or implementation planning until the user responds β€” following the same pause-and-ask pattern as the incomplete description handling"
]
}
]
}
13 changes: 11 additions & 2 deletions plugins/sdlc-workflow/shared/description-digest-protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,17 @@ comment.

## Consumer Verification

The consumer (implement-task) retrieves issue comments and searches for one whose
body starts with the marker string `[sdlc-workflow] Description digest:`. If found:
The consumer (implement-task) retrieves issue comments and searches for those whose
body starts with the marker string `[sdlc-workflow] Description digest:`.

### Multiple Digest Comments

If multiple comments match the marker string (e.g., from plan-feature re-runs or
manual postings), the consumer must select the most recent one by `created`
timestamp. This ensures deterministic behavior without rejecting valid re-planning
scenarios.

If found:

1. Extract the `sha256:<hex-digest>` value
2. Compute SHA-256 of the current description field (same normalization as producer)
Expand Down
50 changes: 49 additions & 1 deletion plugins/sdlc-workflow/skills/implement-task/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ If any of these sections are missing or incomplete, inform the user:

## Step 0.5 – JIRA Access Initialization

Before attempting any JIRA operations (Steps 1, 2, 3, 11), determine the access method.
Before attempting any JIRA operations (Steps 1, 1.5, 2, 3, 11), determine the access method.

**For every JIRA operation:**
1. **Attempt MCP first** (preferred method)
Expand All @@ -49,6 +49,7 @@ Before attempting any JIRA operations (Steps 1, 2, 3, 11), determine the access

**REST API equivalents for this skill's operations:**
- `jira.get_issue(id)` β†’ `python3 scripts/jira-client.py get_issue <id> --fields "*all"`
- `jira.get_issue_comments(id)` β†’ `python3 scripts/jira-client.py get_comments <id>`
- `jira.user_info()` β†’ `python3 scripts/jira-client.py get_user_info`
- `jira.edit_issue(id, assignee=accountId)` β†’ `python3 scripts/jira-client.py update_issue <id> --fields-json '{"assignee": {"id": "<accountId>"}}'`
- `jira.transition_issue(id, status)` β†’ First get transitions with `get_transitions <id>`, find ID for target status, then `transition_issue <id> --transition-id <id>`
Expand Down Expand Up @@ -177,6 +178,53 @@ section in CLAUDE.md (the field is listed as `GitHub Issue custom field: <field-
Store the parsed reference as `<owner>/<repo>#<number>` for use in Step 10.
- **If not configured or the field is empty**, skip silently β€” this is optional.

## Step 1.5 – Verify Description Integrity

After fetching the task, verify that the description has not been modified since
plan-feature created it. This uses the digest protocol defined in
`shared/description-digest-protocol.md`.

1. **Retrieve issue comments**: fetch all comments on the Jira issue:

```
jira.get_issue_comments(<jira-issue-id>)
```

2. **Locate the digest comment**: search for all comments whose body starts with the
marker string `[sdlc-workflow] Description digest:`. This marker is defined in
`shared/description-digest-protocol.md`. If multiple comments match (e.g., from
plan-feature re-runs), select the most recent one by `created` timestamp.

3. **If no digest comment found**: log a warning and proceed normally β€” do not block
execution:

> "No description digest found β€” skipping integrity check. This task may have
> been created before digest tracking was introduced."

4. **If digest comment found**:
a. **Check for comment editing**: if the comment's `created` and `updated`
timestamps are available, compare them. If `updated` is later than `created`,
warn: "Digest comment was edited after initial posting β€” integrity cannot be
fully guaranteed." Proceed with digest comparison regardless. If timestamps
are not available in the API response, skip this check silently.
b. **Extract the stored digest**: parse the `sha256:<hex-digest>` value from the
comment body.
c. **Compute the current digest**: hash the current description field text using
SHA-256, following the same normalization as the protocol (strip
leading/trailing whitespace before hashing). Output a lowercase 64-character
hexadecimal digest.
d. **Compare digests**:
- **Match**: proceed silently β€” no additional user prompt, no added latency.
- **Mismatch**: alert the user that the task description was modified after
plan-feature created it. Display the expected digest (from the comment) and
the actual digest (computed from the current description). Ask the user
whether to:
1. **Proceed** with the current description as-is
2. **Stop** so they can re-run plan-feature to regenerate tasks

**Stop execution immediately** β€” do not proceed with any subsequent steps
until the user responds.

## Step 2 – Verify Dependencies

If the task has Dependencies, check each one:
Expand Down
Loading