From a4cc3498f89cc4bfb6aedfd948681d6a2c4f7288 Mon Sep 17 00:00:00 2001 From: Ruben Romero Montes Date: Thu, 28 May 2026 10:46:30 +0200 Subject: [PATCH 1/2] fix(plan-feature): TC-4570 add self-verification guard to digest computation The digest instructions were prose-style, which let the LLM skip steps and produce placeholder or abbreviated hashes. Restructure as numbered sub-steps with an explicit self-verification checkpoint (step 3) that checks length, character set, and placeholder patterns before posting. Co-Authored-By: Claude Opus 4.6 --- .../skills/plan-feature/SKILL.md | 106 +++++++----------- 1 file changed, 43 insertions(+), 63 deletions(-) diff --git a/plugins/sdlc-workflow/skills/plan-feature/SKILL.md b/plugins/sdlc-workflow/skills/plan-feature/SKILL.md index 8bde4cb6..0ab502b9 100644 --- a/plugins/sdlc-workflow/skills/plan-feature/SKILL.md +++ b/plugins/sdlc-workflow/skills/plan-feature/SKILL.md @@ -652,72 +652,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-.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-.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., ``, ``, `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-.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 `` in this ADF comment: - -```json -{ - "type": "doc", - "version": 1, - "content": [ - { - "type": "paragraph", - "content": [ - { - "type": "text", - "text": "[sdlc-workflow] Description digest: sha256:" - } - ] - } - ] -} -``` - -Replace `` 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: -``` -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 From 9814fa85c77f2ac27ad264f8f394effab2757697 Mon Sep 17 00:00:00 2001 From: Ruben Romero Montes Date: Thu, 28 May 2026 14:37:19 +0200 Subject: [PATCH 2/2] fix(plan-feature): TC-4570 add self-verification to convention applicability and fix bookend templates Convention applicability step 2 was a dense paragraph that the LLM skipped, producing free-form prose rationales and "does NOT apply" annotations. Restructure into four sub-steps (a-d) with self-verification checkpoint, matching the digest fix pattern. Bookend task templates had two issues: "primary repository" was ambiguous in multi-repo features (LLM listed all repos), and "etc." in the omitted-sections line caused Test Requirements to be dropped. Fix both with explicit single-repo rule and exhaustive omission list. Co-Authored-By: Claude Opus 4.6 --- .../skills/plan-feature/SKILL.md | 56 +++++++++++++++---- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/plugins/sdlc-workflow/skills/plan-feature/SKILL.md b/plugins/sdlc-workflow/skills/plan-feature/SKILL.md index 0ab502b9..09e912e9 100644 --- a/plugins/sdlc-workflow/skills/plan-feature/SKILL.md +++ b/plugins/sdlc-workflow/skills/plan-feature/SKILL.md @@ -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 matching the convention's .` - 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 matching the convention's .` + Replace `` with a specific file from Files to Modify or Files to Create. + Replace `` 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 §
: "` 4. Include a reference to an existing file that demonstrates the convention in practice, @@ -579,7 +601,8 @@ bracket the intermediate implementation tasks: - **Summary:** `Create feature branch 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 `` from the @@ -587,14 +610,19 @@ bracket the intermediate implementation tasks: - `## Acceptance Criteria` — the feature branch `` 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 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 `` into `main`. @@ -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