From e0dc8bd0045479bc029467b981605b6facea1009 Mon Sep 17 00:00:00 2001 From: Scott Adams Date: Fri, 10 Apr 2026 15:12:27 -0500 Subject: [PATCH 1/2] feat(skills): add deft-interview skill + strengthen swarm/test-with-code rules (#288 #292 #294 #296) - Create skills/deft-interview/SKILL.md with RFC2119 legend and YAML frontmatter -- deterministic structured Q&A interview loop with 7 rules: one-question-per-turn, numbered options with stated default, other/IDK escape, depth gate, default-acceptance, confirmation gate, and structured handoff contract (answers map); thin pointer and AGENTS.md routing added; deft-setup Phase 1/Phase 2 updated to reference deft-interview; 12 tests - Add read-back verification rule to deft-swarm Phase 6 Step 1 -- after resolving rebase conflicts, re-read resolved file and verify structural integrity before git add; prefer edit_files over shell regex for CHANGELOG.md and SPECIFICATION.md; 2 anti-patterns added - Add Slack release announcement step (Step 6) to deft-swarm Phase 6 -- generates standard announcement block with version, title, summary, key changes, agent count, duration, PR numbers, and release URL - Strengthen test-with-code rule across 4 surfaces: AGENTS.md Before committing (new source files MUST include test files), main.md Decision Making (distinguish regression vs forward coverage), deft-swarm Prompt Template CONSTRAINTS, deft-build pre-commit checklist - Add SPECIFICATION.md acceptance criteria and CHANGELOG.md entries --- .agents/skills/deft-interview/SKILL.md | 9 ++ AGENTS.md | 2 + CHANGELOG.md | 6 ++ SPECIFICATION.md | 24 ++++- main.md | 2 +- skills/deft-build/SKILL.md | 3 +- skills/deft-interview/SKILL.md | 140 +++++++++++++++++++++++++ skills/deft-setup/SKILL.md | 4 +- skills/deft-swarm/SKILL.md | 38 +++++++ tests/content/test_skills.py | 108 +++++++++++++++++++ 10 files changed, 329 insertions(+), 7 deletions(-) create mode 100644 .agents/skills/deft-interview/SKILL.md create mode 100644 skills/deft-interview/SKILL.md diff --git a/.agents/skills/deft-interview/SKILL.md b/.agents/skills/deft-interview/SKILL.md new file mode 100644 index 00000000..cb4d35b0 --- /dev/null +++ b/.agents/skills/deft-interview/SKILL.md @@ -0,0 +1,9 @@ +--- +name: deft-interview +description: >- + Deterministic structured Q&A interview loop. Use when any skill needs + structured user input through focused questions with defaults and + confirmation gate. +--- + +Read and follow: skills/deft-interview/SKILL.md diff --git a/AGENTS.md b/AGENTS.md index ae13f4a1..2a967247 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -56,6 +56,7 @@ When user input matches a trigger keyword, read the corresponding skill: - "setup" / "bootstrap" / "onboard" → `skills/deft-setup/SKILL.md` - "sync" / "good morning" / "update deft" / "update vbrief" / "sync frameworks" → `skills/deft-sync/SKILL.md` - "pre-pr" / "quality loop" / "rwldl" / "self-review" → `skills/deft-pre-pr/SKILL.md` +- "interview" / "ask questions" / "structured interview" → `skills/deft-interview/SKILL.md` ## Development Process (always follow) @@ -68,6 +69,7 @@ When user input matches a trigger keyword, read the corresponding skill: **Before committing:** - Run `task check` (validate + lint + test) — this is the pre-commit gate +- ! New source files (`scripts/`, `src/`, `cmd/`, `*.py`, `*.go`) MUST include corresponding test files in the same PR -- running existing tests alone is not sufficient for new code; forward coverage requires new tests that exercise the new code paths - Add CHANGELOG.md entry under `[Unreleased]` - Verify .github/PULL_REQUEST_TEMPLATE.md checklist items are satisfied diff --git a/CHANGELOG.md b/CHANGELOG.md index 35cba0bf..d9e4589e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added +- **skills/deft-interview/SKILL.md -- deterministic structured Q&A interview skill** (#296, t2.11.1): Created `skills/deft-interview/SKILL.md` with RFC2119 legend and YAML frontmatter encoding a deterministic interview loop any skill can invoke -- 7 rules: one-question-per-turn, numbered options with stated default (`[default: N]`), explicit other/IDK escape option, depth gate, default-acceptance, confirmation gate, and structured handoff contract (answers map); created `.agents/skills/deft-interview/SKILL.md` thin pointer; added AGENTS.md Skill Routing entry; updated deft-setup Phase 1 and Phase 2 to reference deft-interview; added 12 tests +- **deft-swarm Phase 6 Slack release announcement** (#292, t1.22.1): Added Step 6 to `skills/deft-swarm/SKILL.md` Phase 6 -- generates standard Slack announcement block with version, release title, summary, key changes, swarm agent count, duration, PR numbers, and GitHub release URL + ### Fixed +- **deft-swarm Phase 6 read-back verification after rebase conflict resolution** (#288, t1.21.1): Added `!` rule to Phase 6 Step 1 requiring re-read and structural integrity verification after resolving rebase conflicts and before `git add`; added `!` rule preferring `edit_files` over shell regex for CHANGELOG.md/SPECIFICATION.md; added 2 anti-patterns +- **Strengthen test-with-code rule across 4 surfaces** (#294, t1.23.1): Added `!` rule to AGENTS.md Before committing requiring new source files to include test files; updated main.md testing gate to distinguish regression vs forward coverage; added constraint to deft-swarm Prompt Template; added forward test coverage check to deft-build pre-commit checklist - **Resolve 5 untracked xfail gaps in known_failures.json** (#295, t1.24.1): Flipped 20 xfail entries to passing across 5 gap categories -- (1) flipped 3 stale xfails for root PROJECT.md and core/project.md (already cleaned in prior PRs); (2) created tools/taskfile-migration.md stub to resolve broken See also link from tools/taskfile.md; (3) standardized RFC2119 legend format in 5 context/*.md files and added legend to languages/commands.md; (4) added missing shape sections to 8 files (## Commands to languages/6502-DASM.md, languages/markdown.md, languages/mermaid.md; ## Workflow to strategies/discuss.md, strategies/research.md; ## Framework Selection or ## Core Architecture to interfaces/cli.md, interfaces/rest.md, interfaces/web.md); (5) rephrased deprecated path and legacy name references in specs/testbed/SPECIFICATION.md to avoid triggering content tests ### Changed diff --git a/SPECIFICATION.md b/SPECIFICATION.md index 56d91180..1fb1c5e6 100644 --- a/SPECIFICATION.md +++ b/SPECIFICATION.md @@ -1055,7 +1055,10 @@ Agents on Windows writing files via PowerShell reach for [System.Text.Encoding]: Add ! rule to skills/deft-swarm/SKILL.md Phase 6 Step 1: after resolving any rebase conflict and before running git add, re-read the resolved file and verify structural integrity (no conflict markers, no collapsed lines, no encoding artifacts). Prefer edit_files over shell regex for CHANGELOG.md and SPECIFICATION.md conflict resolution. Mirrors mandatory pre-commit file review from t1.11.4, targeted at the rebase conflict resolution path. Closes #288. -- +- skills/deft-swarm/SKILL.md Phase 6 Step 1 contains ! rule for read-back verification after conflict resolution: re-read file, check no conflict markers, no collapsed lines, no encoding artifacts +- skills/deft-swarm/SKILL.md Phase 6 Step 1 contains ! rule preferring edit_files over shell regex for CHANGELOG.md and SPECIFICATION.md conflict resolution +- skills/deft-swarm/SKILL.md Anti-Patterns contains entry prohibiting git add without read-back verification +- tests/content/test_skills.py passes **Traces**: #288 @@ -1063,7 +1066,10 @@ Add ! rule to skills/deft-swarm/SKILL.md Phase 6 Step 1: after resolving any reb Add a step to skills/deft-swarm/SKILL.md Phase 6 (after creating the GitHub release) that generates a standard Slack announcement block and presents it to the user. Include version, release title, summary, key changes, swarm agent count, approximate duration, PR numbers, and GitHub release URL. Closes #292. -- +- skills/deft-swarm/SKILL.md Phase 6 contains Step 6: Generate Slack Release Announcement after GitHub release +- Announcement template includes: version, release title, summary, key changes, agent count, duration, PR numbers, GitHub release URL +- Step uses ! rules for all required fields +- tests/content/test_skills.py passes **Traces**: #292 @@ -1071,7 +1077,11 @@ Add a step to skills/deft-swarm/SKILL.md Phase 6 (after creating the GitHub rele Strengthen the testing enforcement gate across 4 surfaces: (1) AGENTS.md Before committing: ! rule -- new source files (scripts/, src/, cmd/, *.py, *.go) MUST include corresponding test files in the same PR; running existing tests is not sufficient. (2) main.md Decision Making: update t1.6.1 testing gate to distinguish regression (existing tests pass) from forward coverage (new code has new tests). (3) deft-swarm SKILL.md prompt template CONSTRAINTS: new source files must have corresponding tests. (4) deft-build SKILL.md pre-commit checklist: for each new source file in this PR, verify a corresponding test file exists. Future deterministic gate (task verify:test-coverage) deferred to #233 Phase 5. Closes #294. -- +- AGENTS.md Before committing section contains ! rule: new source files MUST include corresponding test files in the same PR +- main.md Decision Making testing gate distinguishes regression coverage (existing tests pass) from forward coverage (new code has new tests) +- skills/deft-swarm/SKILL.md Prompt Template CONSTRAINTS contains new source files must have corresponding tests +- skills/deft-build/SKILL.md pre-commit checklist contains forward test coverage check +- tests/content/test_skills.py passes **Traces**: #294 @@ -1087,7 +1097,13 @@ Fix all 5 untracked xfail gaps in a single cleanup PR: (1) remove or replace lea Create skills/deft-interview/SKILL.md with RFC2119 legend and frontmatter encoding a deterministic interview loop any skill can invoke: one-question-per-turn rule, numbered options with stated default (e.g. [default: 3]), explicit other/IDK escape option, depth gate (! keep asking until no material ambiguity remains), default-acceptance rule (bare enter/yes/default accepts stated default), confirmation gate (display all captured answers and require yes/no before proceeding), and structured handoff contract (answers map for calling skill). Create .agents/skills/deft-interview/SKILL.md thin pointer. Update AGENTS.md Skill Routing table with trigger keywords (interview, ask questions, structured interview). Update deft-setup SKILL.md Phase 1 and Phase 2 to reference deft-interview for Q&A loops. Add tests/content/test_skills.py coverage. Anti-patterns: asking multiple questions at once, proceeding without confirmation gate, omitting defaults, omitting other escape. Closes #296. -- +- skills/deft-interview/SKILL.md exists with RFC2119 legend and YAML frontmatter +- Contains 7 rules: one-question-per-turn, numbered options with stated default, other/IDK escape, depth gate, default acceptance, confirmation gate, structured handoff contract +- Anti-patterns section covers: multiple questions, missing confirmation gate, missing defaults, missing escape option +- .agents/skills/deft-interview/SKILL.md thin pointer exists +- AGENTS.md Skill Routing table contains interview / ask questions / structured interview entry +- skills/deft-setup/SKILL.md Phase 1 and Phase 2 reference deft-interview +- tests/content/test_skills.py covers new skill with 12 tests **Traces**: #296 diff --git a/main.md b/main.md index 63a68aa4..eee3ce0b 100644 --- a/main.md +++ b/main.md @@ -49,7 +49,7 @@ Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY. - ~ Suggest improvements even when not asked - ! Before implementing any planned change that touches 3+ files or has an accepted plan artifact, propose `/deft:change ` and present the change name for explicit confirmation (e.g. "Confirm? yes/no") — the user must reply with an affirmative (`yes`, `confirmed`, `approve`) to satisfy this gate; a broad 'proceed', 'do it', or 'go ahead' does NOT satisfy it - ? For solo projects (single contributor): the `/deft:change` proposal is RECOMMENDED but not mandatory for changes fully covered by the quality gate (`task check`); it remains mandatory for cross-cutting, architectural, or high-risk changes regardless of team size -- ! No implementation is complete until tests are written and `task check` passes — this gate applies unconditionally and a general 'proceed' instruction does not waive it +- ! No implementation is complete until tests are written and `task check` passes — this gate applies unconditionally and a general 'proceed' instruction does not waive it. This gate has two dimensions: (a) **regression coverage** -- existing tests continue to pass, and (b) **forward coverage** -- new source files (`scripts/`, `src/`, `cmd/`, `*.py`, `*.go`) have corresponding new test files that exercise the new code paths. Running existing tests alone satisfies (a) but not (b) - ⊗ Commit or push directly to the default branch (master/main) — always create a feature branch and open a PR, even for single-commit changes. The only exception is if the user **explicitly** instructs a direct commit for the current task, or if `PROJECT.md` contains `Allow direct commits to master: true` under `## Branching`. - ⊗ Fix a discovered issue in-place mid-task without filing a GitHub issue — always file the issue and continue the current task; do not derail the active workflow to apply an instant fix (#198). **Carve-out**: if the discovered issue is a hard blocker (the current task literally cannot be completed without fixing it), fixing it in-scope is permitted, but a GitHub issue MUST be filed before or alongside the fix; nice-to-fix, quality improvements, and adjacent issues remain prohibited (#241) - ⊗ Continue executing a skill past its explicit instruction boundary — when a skill's steps are complete, stop and return to the calling context; do not drift into adjacent work (#198) diff --git a/skills/deft-build/SKILL.md b/skills/deft-build/SKILL.md index 4df21fb6..e2c41f4e 100644 --- a/skills/deft-build/SKILL.md +++ b/skills/deft-build/SKILL.md @@ -140,8 +140,9 @@ See `deft/coding/coding.md` and `deft/coding/testing.md` for full rules. 2. ! **Unintended duplication** -- accidental double entries in CHANGELOG.md, SPECIFICATION.md, or structured data files 3. ! **Structural issues** -- malformed CHANGELOG entries, broken table rows, mismatched index entries, invalid JSON/YAML 4. ! **Semantic accuracy** -- verify that counts, claims, and summaries in CHANGELOG entries and ROADMAP changelog lines match the actual data in the commit (e.g. "triaged 4 issues" must match the number actually triaged, issue numbers cited must match the issues actually added) -5. ! **Semantic contradictions** -- when adding a `!` or `⊗` rule that prohibits a specific command, pattern, or behavior, search the same file for any `~`, `≉`, or prose that recommends or permits the same command/pattern -- resolve all contradictions in the same commit before pushing +5. ! **Semantic contradictions** -- when adding a `!` or `⊗` rule that prohibits a specific command, pattern, or behavior, search the same file for any `~`, `≉`, or prose that recommends or permits the same command/pattern -- resolve all contradictions in the same commit before pushing 6. ! **Strength duplicates** -- when strengthening a rule (e.g. upgrading `~` to `!`), grep for the term in the full file and verify no weaker-strength duplicate remains +7. ! **Forward test coverage** -- for each new source file in this PR (`scripts/`, `src/`, `cmd/`, `*.py`, `*.go`), verify a corresponding test file exists in the same PR; running existing tests is not sufficient for new code ⊗ Commit without re-reading all modified files first. diff --git a/skills/deft-interview/SKILL.md b/skills/deft-interview/SKILL.md new file mode 100644 index 00000000..75d2ae30 --- /dev/null +++ b/skills/deft-interview/SKILL.md @@ -0,0 +1,140 @@ +--- +name: deft-interview +description: > + Deterministic structured Q&A interview loop. Use when any skill needs to + gather structured input from the user through a series of focused questions + with numbered options, stated defaults, and a confirmation gate before + artifact generation. +--- + +# Deft Interview + +Deterministic interview loop that any skill can invoke to gather structured user input. + +Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY. + +## When to Use + +- Another skill needs to gather structured input from the user (e.g. deft-setup Phase 1/Phase 2) +- User says "interview", "ask questions", or "structured interview" +- A workflow requires a series of focused questions with explicit defaults and confirmation before proceeding + +## Interview Loop + +### Rule 1: One Question Per Turn + +! Ask ONE focused question per step. After the user answers, send the NEXT question in a new message. Repeat until all questions for the current interview are answered. + +- ⊗ Include two or more questions in the same message under any circumstances +- ⊗ List upcoming questions -- only show the current one +- ⊗ Combine the current question with a summary of previous answers unless explicitly at the confirmation gate + +### Rule 2: Numbered Options with Stated Default + +! Every question MUST present numbered answer options. Exactly one option MUST be marked as the default using the `[default: N]` notation inline. + +Example: +``` +Which deployment platform? +1. Cross-platform (Linux / macOS / Windows) +2. Web / Cloud [default: 2] +3. Embedded / low-resource +4. Other / I don't know +``` + +- ! The default MUST be stated inline with the option (e.g. `[default: 2]`), not in a separate line or footnote +- ! If no option is objectively better, pick the most common choice and mark it as default +- ~ Use structured question tools (AskQuestion, question picker, multi-choice UI) when available + +### Rule 3: Explicit "Other / I Don't Know" Escape + +! Every question MUST include an escape option. The last numbered option MUST be either: +- "Other (please specify)" -- for open-ended alternatives +- "I don't know" -- when the user may lack context to answer +- "Other / I don't know" -- combined form (preferred) + +- ⊗ Present a question with no escape option -- the user must always have a way out +- ~ When the user selects the escape option, follow up with a brief open-ended prompt to capture their input or acknowledge the gap + +### Rule 4: Depth Gate + +! Keep asking until no material ambiguity remains before artifact generation. The interview is NOT complete until the calling skill's required inputs are all captured with sufficient specificity to generate the target artifact. + +- ! If an answer introduces new ambiguity (e.g. user selects "Other" and describes something that requires follow-up), ask clarifying questions before moving on +- ! Do not truncate the interview to save time -- completeness takes priority over brevity +- ~ The calling skill defines what "sufficient specificity" means by providing a list of required fields in the handoff contract + +### Rule 5: Default Acceptance + +! When a question has a stated default, the user may accept it with any of the following responses: +- Bare enter / empty response +- "yes", "y", "ok", "default", "keep" +- The default option number (e.g. "2") + +! Do NOT re-ask the question when the user accepts the default. Record the default value and proceed to the next question. + +- ⊗ Re-ask a question because the user's acceptance was "too brief" -- any of the listed responses is a valid acceptance +- ⊗ Interpret an empty response as a refusal or skip + +### Rule 6: Confirmation Gate + +! After ALL questions are answered (depth gate satisfied), display a summary of ALL captured answers in a clearly formatted list and require explicit yes/no confirmation before proceeding. + +Format: +``` +Here are the values I captured: + +- **Field 1**: value +- **Field 2**: value +- **Field 3**: value +... + +Confirm these values? (yes / no) +``` + +- ! Accept only explicit affirmative responses (`yes`, `confirmed`, `approve`) -- reject vague responses (`proceed`, `do it`, `go ahead`) +- ! If the user says `no`: ask which values to correct, re-ask those specific questions only (do not restart the full interview), then re-display the updated summary and re-confirm +- ! If any value appears to be auto-generated filler (repeated default text, placeholder strings, or values that echo the question prompt), warn the user explicitly before confirming +- ⊗ Proceed to artifact generation without displaying the summary and receiving explicit confirmation + +### Rule 7: Structured Handoff Contract + +! When the interview is complete (confirmation gate passed), the skill exits with an **answers map** -- a structured key-value representation of all captured answers that the calling skill uses to generate artifacts. + +The answers map format: +```json +{ + "field_1": "captured value", + "field_2": "captured value", + "field_3": ["list", "if", "multi-select"], + ... +} +``` + +- ! The calling skill defines the expected keys in its invocation of deft-interview +- ! The answers map MUST contain a value for every required key defined by the calling skill +- ! Optional keys may be omitted if the user did not provide input and no default was applicable +- ~ The calling skill is responsible for validating the answers map against its own schema and requesting re-interview for any missing or invalid fields + +## Invocation Contract + +When a calling skill invokes deft-interview, it MUST provide: + +1. **Required fields**: list of field names that must be captured (the depth gate uses this to determine completeness) +2. **Question definitions**: for each field, the question text, numbered options (if applicable), and default value +3. **Optional fields**: list of field names that may be skipped + +The calling skill MAY provide: +- **Context preamble**: a brief description of why these questions are being asked (shown to the user before the first question) +- **Validation rules**: constraints on acceptable values for specific fields + +## Anti-Patterns + +- ⊗ Ask multiple questions in a single message -- one question per turn, always +- ⊗ Proceed to artifact generation without the confirmation gate -- all captured answers must be displayed and explicitly confirmed +- ⊗ Omit the default marker from any question -- every question must have a `[default: N]` option +- ⊗ Omit the "Other / I don't know" escape from any question -- every question must have an escape option +- ⊗ Re-ask a question after the user accepted the default -- move on immediately +- ⊗ Skip the depth gate and generate artifacts with known ambiguity remaining +- ⊗ Exit the interview without producing a structured answers map for the calling skill +- ⊗ Combine interview questions with artifact generation in the same message diff --git a/skills/deft-setup/SKILL.md b/skills/deft-setup/SKILL.md index 861e8d7f..0638a2ef 100644 --- a/skills/deft-setup/SKILL.md +++ b/skills/deft-setup/SKILL.md @@ -104,6 +104,8 @@ Expected USER.md fields: **Name**, **Custom Rules**, **Default Strategy**, and o ### Interview Rules +! This phase follows the deterministic interview loop defined in `skills/deft-interview/SKILL.md`. The core rules (one question per turn, numbered options with stated default, explicit "other" escape, depth gate, default acceptance, confirmation gate, structured handoff) apply here. Key points repeated for emphasis: + ! **Each message you send MUST contain exactly ONE question.** This is the most important rule in this file. After the user answers, send the NEXT question in a new message. Repeat until all questions for their track are answered. @@ -249,7 +251,7 @@ Wait for answer. Then follow the corresponding track in the Question Sequence be ### Interview Rules (same as Phase 1) ! **Each message MUST contain exactly ONE question.** The Phase 1 interview rules -apply here too. Do not combine questions. +apply here too. Do not combine questions. See `skills/deft-interview/SKILL.md` for the canonical deterministic interview loop. ### Question Sequence diff --git a/skills/deft-swarm/SKILL.md b/skills/deft-swarm/SKILL.md index 215c40a3..7402c077 100644 --- a/skills/deft-swarm/SKILL.md +++ b/skills/deft-swarm/SKILL.md @@ -275,6 +275,13 @@ All PRs meet ALL of: ! **Rebase cascade ownership:** Monitor owns rebase cascade sequencing. Swarm agents do not rebase -- by the time merges begin, swarm agents are idle or complete. The monitor fetches updated master, rebases each remaining branch, resolves conflicts, and force-pushes. +! **Read-back verification after conflict resolution:** After resolving any rebase conflict and BEFORE running `git add`, re-read the resolved file and verify structural integrity: +- ! No conflict markers remain (`<<<<<<<`, `=======`, `>>>>>>>`) +- ! No collapsed or missing lines (compare line count to pre-rebase version if feasible) +- ! No encoding artifacts (BOM injection, mojibake, replacement characters) +- ! For `CHANGELOG.md` and `SPECIFICATION.md` conflicts: prefer `edit_files` over shell regex (`sed`, `Select-String -replace`) for resolution -- edit_files preserves encoding and provides exact match verification, while regex substitutions risk silent line collapse or encoding corruption +- ⊗ Run `git add` on a conflict-resolved file without first re-reading it and verifying structural integrity + ! **Non-interactive rebase:** Monitor MUST set `GIT_EDITOR=true` (Unix/WSL/Git Bash) or `$env:GIT_EDITOR="echo"` (Windows PowerShell) before running `git rebase --continue` during merge cascade to prevent the default editor from blocking the agent. ! **Merge cascade warning:** Shared append-only files (CHANGELOG.md, SPECIFICATION.md) cause merge conflicts when PRs are merged sequentially — each merge changes the insertion point, conflicting remaining PRs. Each conflict requires rebase → push → wait for checks (~3 min) + ~2-5 min Greptile re-review per rebase. Plan for N-1 rebase cycles × ~3 min CI + ~2-5 min Greptile re-review per rebase when merging N PRs. @@ -317,6 +324,34 @@ All PRs meet ALL of: ⊗ Update ROADMAP.md during swarm close — leave it for the release commit. +### Step 6: Generate Slack Release Announcement + +! After creating the GitHub release (or after the final merge if no formal release is created), generate a standard Slack announcement block and present it to the user for copy-paste into the team channel. + +! The announcement block MUST include all of the following fields: + +``` +:rocket: *{Project Name} {version}* -- {release title} + +*Summary*: {one-sentence description of the release scope} + +*Key Changes*: +- {bullet per significant change, 3-5 items max} + +*Stats*: {N} agents | ~{duration} elapsed | {N} PRs merged +*PRs*: {#PR1, #PR2, ...} +*Release*: {GitHub release URL} +``` + +- ! Populate version from the CHANGELOG promotion commit or git tag +- ! Populate release title from the CHANGELOG section heading or GitHub release title +- ! Key changes summarized from CHANGELOG `[Unreleased]` entries (not raw commit messages) +- ! Agent count and approximate duration from the swarm session (Phase 3 launch to Phase 6 close) +- ! PR numbers from the merged PRs in this swarm run +- ! GitHub release URL from the `gh release create` output (or `gh release view --json url` if already created) +- ~ Present the block as a code-fenced snippet the user can copy directly +- ? If no formal GitHub release was created (e.g. user deferred), still generate the announcement with a placeholder URL and note that the release is pending + ## Crash Recovery When a monitor session crashes or a new session must take over an in-progress swarm, follow these steps to safely reconstruct and continue. @@ -387,6 +422,7 @@ Greptile review cycle on the PR. Do NOT merge — leave for human review. CONSTRAINTS: - Do not touch [list files other agents are working on] +- New source files (scripts/, src/, cmd/, *.py, *.go) must have corresponding test files in the same PR - Use conventional commits: type(scope): description - Run task check before every commit - Never force-push @@ -426,3 +462,5 @@ CONSTRAINTS: - ⊗ Proceed to the next merge in the rebase cascade before confirming the Greptile re-review is current (SHA match) and exit condition is met (confidence > 3, no P0/P1) on the rebased branch -- see `skills/deft-review-cycle/SKILL.md` Step 4 for the monitoring approach - ⊗ Spawn a replacement sub-agent without confirming the original is unresponsive via a lifecycle event (idle/blocked) — original Warp tabs can resume after apparent failure, and two concurrent agents on the same worktree will corrupt the tool_use/tool_result call chain (#261, #263) - ⊗ Skip Phase 5 or the Phase 5→6 confirmation gate under time pressure or due to long context — the gate is mandatory regardless of conversation length, elapsed time, or context-window pressure +- ⊗ Run `git add` on a conflict-resolved file without re-reading and verifying structural integrity (no conflict markers, no collapsed lines, no encoding artifacts) -- see Phase 6 Step 1 read-back verification rule (#288) +- ⊗ Use shell regex (`sed`, `Select-String -replace`) to resolve `CHANGELOG.md` or `SPECIFICATION.md` rebase conflicts -- prefer `edit_files` for encoding safety and exact match verification (#288) diff --git a/tests/content/test_skills.py b/tests/content/test_skills.py index 37bc7b86..17ddb7fa 100644 --- a/tests/content/test_skills.py +++ b/tests/content/test_skills.py @@ -960,3 +960,111 @@ def test_deft_setup_deft_version_must_rule() -> None: assert "\u2297" in text and "without including the `deft_version` field" in text, ( f"{_SETUP_PATH}: must have \u2297 anti-pattern against omitting deft_version (#270, t3.2.1)" ) + + +# --------------------------------------------------------------------------- +# 30. deft-interview skill -- existence, structure, and content (#296, t2.11.1) +# --------------------------------------------------------------------------- + +_INTERVIEW_PATH = "skills/deft-interview/SKILL.md" +_INTERVIEW_POINTER_PATH = ".agents/skills/deft-interview/SKILL.md" + + +def test_deft_interview_exists() -> None: + """deft-interview SKILL.md must exist at its expected path.""" + assert (_REPO_ROOT / _INTERVIEW_PATH).is_file(), ( + f"Skill file missing: {_INTERVIEW_PATH}" + ) + + +def test_deft_interview_rfc2119_legend() -> None: + """deft-interview must contain the RFC2119 legend line.""" + text = _read_skill(_INTERVIEW_PATH) + assert RFC2119_LEGEND in text, ( + f"{_INTERVIEW_PATH}: missing RFC2119 legend '{RFC2119_LEGEND}'" + ) + + +def test_deft_interview_has_frontmatter() -> None: + """deft-interview must have YAML frontmatter with name and description.""" + text = _read_skill(_INTERVIEW_PATH) + assert text.startswith("---"), ( + f"{_INTERVIEW_PATH}: must start with YAML frontmatter '---'" + ) + assert "name: deft-interview" in text, ( + f"{_INTERVIEW_PATH}: frontmatter must contain 'name: deft-interview'" + ) + + +def test_deft_interview_one_question_per_turn() -> None: + """deft-interview must enforce one-question-per-turn rule.""" + text = _read_skill(_INTERVIEW_PATH) + assert "ONE focused question per step" in text, ( + f"{_INTERVIEW_PATH}: must contain one-question-per-turn rule (#296)" + ) + + +def test_deft_interview_numbered_options_with_default() -> None: + """deft-interview must require numbered options with stated default.""" + text = _read_skill(_INTERVIEW_PATH) + assert "[default:" in text and "numbered answer options" in text.lower(), ( + f"{_INTERVIEW_PATH}: must require numbered options with stated default (#296)" + ) + + +def test_deft_interview_other_escape() -> None: + """deft-interview must require an other/IDK escape option.""" + text = _read_skill(_INTERVIEW_PATH) + assert "Other / I don't know" in text, ( + f"{_INTERVIEW_PATH}: must require other/IDK escape option (#296)" + ) + + +def test_deft_interview_depth_gate() -> None: + """deft-interview must include a depth gate rule.""" + text = _read_skill(_INTERVIEW_PATH) + assert "no material ambiguity remains" in text.lower(), ( + f"{_INTERVIEW_PATH}: must include depth gate rule (#296)" + ) + + +def test_deft_interview_default_acceptance() -> None: + """deft-interview must define default acceptance responses.""" + text = _read_skill(_INTERVIEW_PATH) + assert "bare enter" in text.lower() and "default" in text.lower(), ( + f"{_INTERVIEW_PATH}: must define default acceptance responses (#296)" + ) + + +def test_deft_interview_confirmation_gate() -> None: + """deft-interview must require confirmation gate with all captured answers.""" + text = _read_skill(_INTERVIEW_PATH) + assert "confirmation gate" in text.lower() and "yes / no" in text.lower(), ( + f"{_INTERVIEW_PATH}: must require confirmation gate (#296)" + ) + + +def test_deft_interview_structured_handoff() -> None: + """deft-interview must define structured handoff contract with answers map.""" + text = _read_skill(_INTERVIEW_PATH) + assert "answers map" in text.lower() and "calling skill" in text.lower(), ( + f"{_INTERVIEW_PATH}: must define structured handoff contract (#296)" + ) + + +def test_deft_interview_anti_patterns() -> None: + """deft-interview must have anti-patterns section.""" + text = _read_skill(_INTERVIEW_PATH) + assert "## Anti-Patterns" in text, ( + f"{_INTERVIEW_PATH}: missing '## Anti-Patterns' section (#296)" + ) + assert "multiple questions" in text.lower() and "confirmation gate" in text.lower(), ( + f"{_INTERVIEW_PATH}: anti-patterns must cover multi-question and confirmation gate (#296)" + ) + + +def test_deft_interview_pointer_exists() -> None: + """.agents thin pointer for deft-interview must exist.""" + assert (_REPO_ROOT / _INTERVIEW_POINTER_PATH).is_file(), ( + f"Thin pointer missing: {_INTERVIEW_POINTER_PATH}" + ) From 587bafb05cd65432530923b451f13fc0c9d34df0 Mon Sep 17 00:00:00 2001 From: Scott Adams Date: Fri, 10 Apr 2026 15:18:33 -0500 Subject: [PATCH 2/2] fix: address Greptile review findings (batch) - Add 4 tests for deft-swarm Phase 6 read-back verification (#288) and Slack announcement (#292) to match codebase pattern of testing every new skill section (P2 finding from Greptile review) --- tests/content/test_skills.py | 42 ++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/tests/content/test_skills.py b/tests/content/test_skills.py index 17ddb7fa..7c4ca748 100644 --- a/tests/content/test_skills.py +++ b/tests/content/test_skills.py @@ -1068,3 +1068,45 @@ def test_deft_interview_pointer_exists() -> None: assert (_REPO_ROOT / _INTERVIEW_POINTER_PATH).is_file(), ( f"Thin pointer missing: {_INTERVIEW_POINTER_PATH}" ) + + +# --------------------------------------------------------------------------- +# 31. deft-swarm Phase 6 read-back verification (#288, t1.21.1) +# --------------------------------------------------------------------------- + + +def test_deft_swarm_phase6_readback_verification() -> None: + """Phase 6 must require re-reading conflict-resolved files before git add.""" + text = _read_skill(_SWARM_PATH) + assert "Read-back verification" in text and "conflict markers" in text.lower(), ( + f"{_SWARM_PATH}: Phase 6 must contain read-back verification rule (#288)" + ) + + +def test_deft_swarm_phase6_prefer_edit_files_for_conflicts() -> None: + """Phase 6 must prefer edit_files over shell regex for conflict resolution.""" + text = _read_skill(_SWARM_PATH) + assert "edit_files" in text and "CHANGELOG.md" in text and "SPECIFICATION.md" in text, ( + f"{_SWARM_PATH}: Phase 6 must prefer edit_files for conflict resolution (#288)" + ) + + +# --------------------------------------------------------------------------- +# 32. deft-swarm Phase 6 Slack announcement (#292, t1.22.1) +# --------------------------------------------------------------------------- + + +def test_deft_swarm_phase6_slack_announcement_step() -> None: + """Phase 6 Step 6 must generate a Slack release announcement block.""" + text = _read_skill(_SWARM_PATH) + assert "Slack" in text and "announcement" in text.lower(), ( + f"{_SWARM_PATH}: Phase 6 must include Slack announcement step (#292)" + ) + + +def test_deft_swarm_phase6_slack_required_fields() -> None: + """Slack announcement must include version, key changes, PR numbers, and release URL.""" + text = _read_skill(_SWARM_PATH) + assert "Key Changes" in text and "PRs*:" in text and "Release*:" in text, ( + f"{_SWARM_PATH}: Slack announcement must include required fields (#292)" + )