diff --git a/.cursor/rules/automatic-openspec-workflow.mdc b/.cursor/rules/automatic-openspec-workflow.mdc index 8264b9ef..8a52b3d7 100644 --- a/.cursor/rules/automatic-openspec-workflow.mdc +++ b/.cursor/rules/automatic-openspec-workflow.mdc @@ -5,11 +5,31 @@ alwaysApply: true # Automatic OpenSpec Workflow -This rule ensures that all code changes in the specfact-cli codebase are properly tracked through OpenSpec change proposals, following the spec-driven development workflow. +This rule ensures that all code changes in the specfact-cli codebase are properly tracked through OpenSpec change proposals, following the spec-driven development workflow. **No application code may be modified without a corresponding OpenSpec change (new or delta) unless the user explicitly opts out.** + +## Critical: Before Any Code Modification + +**Do not add, modify, or delete any application code** (in `src/`, `tools/`, tests, or significant docs) until all of the following are done: + +1. **Read and apply `openspec/config.yaml`:** + - Use the project context (tech stack, constraints, architecture, SDD+TDD discipline) for all artifact work. + - Apply per-artifact rules (proposal, specs, design, tasks) when creating or updating any change artifact. + +2. **Ensure an OpenSpec change exists for the intended modification:** + - **New work:** Create a new change (e.g. via `/opsx:new`, `/opsx:ff`, or `/wf-create-change-from-plan`). + - **Existing change:** Update the existing change (proposal, specs, design, tasks) or create a **delta change** that updates the existing spec (e.g. via openspec archive after implementation). + - There must be no code change without a corresponding change proposal (new or delta) that describes it. + +3. **Validate the change before implementing:** + - Run `openspec validate --strict`. + - Optionally run `/wf-validate-change ` for breaking-change and dependency analysis. + - Do not proceed to implementation until validation passes (or the user explicitly overrides). + +**Exception:** Only when the user explicitly says "skip openspec", "direct implementation", "simple fix", "just fix it", or similar, may you implement without creating or updating an OpenSpec change. ## When This Rule Applies -This rule automatically triggers when the user requests to: +This rule applies to **every** request that would result in: - **Add** new features, functions, classes, or capabilities - **Modify** existing code, functions, or behavior @@ -19,23 +39,25 @@ This rule automatically triggers when the user requests to: - **Implement** new features or capabilities - **Enhance** existing functionality - **Remove** features or code (unless explicitly a simple deletion) +- **Bug fixes** that restore intended behavior (including simple fixes) +- **Tests for existing behavior** (adding tests to existing code) +- **Typos, formatting, or comments** (cosmetic changes) +- **Dependency updates** (breaking and non-breaking) +- **Configuration changes** (including simple config updates) + +For any such request, **before** writing or modifying any code, follow the steps below so that a change (new or delta) exists and is validated. If the work relates to an already-implemented change, create an OpenSpec delta change to update the existing spec (e.g. via openspec archive after implementation). ## What This Rule Does NOT Apply To -Skip OpenSpec workflow for: +Skip OpenSpec workflow only when: -- **Bug fixes** that restore intended behavior (simple fixes) -- **Typos, formatting, or comments** (cosmetic changes) -- **Dependency updates** (non-breaking) -- **Configuration changes** (simple config updates) -- **Tests for existing behavior** (adding tests to existing code) -- **User explicitly says "skip openspec"** or "direct implementation" +- **User explicitly says** "skip openspec", "no openspec", "direct implementation", "implement directly", "simple fix", or "just fix it" ## Automatic Workflow Steps -### Step 1: Detect Change Request +### Step 1: Detect Change Request (No Code Modification Yet) -When user requests a change, immediately: +When user requests a change, **do not write or modify any application code yet**. Instead: 1. **Parse the request** to understand: - What is being changed (feature, function, module, etc.) @@ -43,22 +65,24 @@ When user requests a change, immediately: - Affected files or modules (if mentioned) 2. **Determine if OpenSpec workflow is needed:** - - If request matches "What This Rule Applies To" → proceed + - If request matches "When This Rule Applies" → proceed with Steps 2–4 (create/update change, validate), then implement only after change is ready - If request matches "What This Rule Does NOT Apply To" → skip OpenSpec, implement directly - If unclear → ask user: "Should this be tracked as an OpenSpec change, or is this a simple fix?" +3. **Read `openspec/config.yaml`** before creating or updating any change artifact. Apply project context and per-artifact rules to all proposal, spec, design, and task content. + ### Step 2: Search for Existing OpenSpec Changes **Before creating a new change, always check for existing work:** -1. **Navigate to specfact-cli-internal workspace:** - - Change directory to `/home/dom/git/nold-ai/specfact-cli-internal` +1. **Navigate to specfact-cli workspace:** + - Change directory to `specfact-cli` inside the project workspace - Verify `openspec/` directory exists 2. **List active changes:** ```bash - cd /home/dom/git/nold-ai/specfact-cli-internal + cd /specfact-cli openspec list ``` @@ -78,6 +102,8 @@ When user requests a change, immediately: ### Step 3: Create or Update OpenSpec Change +**Required:** Use `openspec/config.yaml` (project context and per-artifact rules) for all artifact creation and updates. Do not create or update proposal, specs, design, or tasks without applying config.yaml rules. + **If creating a new change:** 1. **Gather requirements:** @@ -96,16 +122,16 @@ When user requests a change, immediately: 3. **Execute workflow command:** **For ad-hoc changes (no plan document):** - - Use: `/openspec-proposal` command directly + - Use: `/opsx-explore` to research codebase for potential conflicts, dependencies, and clarify, then use `/opsx-new` (or `/opsx:ff`) to create the change proposal - Follow the command steps: - - Review `openspec/config.yaml` (OPSX) or `openspec/project.md` (legacy) and existing specs + - Review `openspec/config.yaml` and existing specs - Choose unique verb-led `change-id` - Scaffold `proposal.md`, `tasks.md`, optional `design.md` - Create spec deltas in `changes//specs//spec.md` - Validate with `openspec validate --strict` **For changes from plan documents:** - - Use: `/specfact-cli-internal/wf-create-change-from-plan ` + - Use: `/specfact-cli/wf-create-change-from-plan ` - Follow the workflow steps: - Plan selection and discovery - Plan review and alignment check @@ -125,25 +151,34 @@ When user requests a change, immediately: - Read `openspec/changes//proposal.md` - Read `openspec/changes//tasks.md` - Read `openspec/changes//specs/` (if exists) + - Read `openspec/changes//design.md` (if exists) + - Read `openspec/changes//CHANGE_VALIDATION.md` (if exists) 2. **Update change artifacts:** - Update `proposal.md` if scope changed - - Add new tasks to `tasks.md` if needed + - Add new tasks to `tasks.md` if needed and adhere to config.yaml rules - Update spec deltas if requirements changed + - Update design.md if architectural decisions changed 3. **Validate updated change:** ```bash - cd /home/dom/git/nold-ai/specfact-cli-internal + cd /specfact-cli openspec validate --strict ``` + Then run `/specfact-cli/wf-validate-change ` to validate the updated change + - If validation fails, fix issues in proposal.md, tasks.md, design.md (if exists), or spec deltas + - Re-validate until passing + - Continue until validation passes + - If validation passes, update CHANGE_VALIDATION.md with validation result + 4. **Inform user:** - "Updated existing OpenSpec change: ``" ### Step 4: Verify and Apply Change -**After change is created or updated:** +**After change is created or updated (still no code modification until user confirms):** 1. **Review the change:** - Display summary of the change proposal @@ -151,12 +186,12 @@ When user requests a change, immediately: - Confirm with user: "OpenSpec change ready. Proceed with implementation?" 2. **If user confirms or if workflow requires immediate application:** - - Execute: `/specfact-cli-internal/wf-apply-change ` + - Execute: `/opsx:apply ` (or `/specfact-cli/wf-apply-change `) - Follow workflow steps: - Change selection - Read change artifacts - Execute openspec-apply workflow - - Complete tasks sequentially + - Complete tasks sequentially (TDD: tests first, then code) - Update task checklist - Completion and summary @@ -165,41 +200,62 @@ When user requests a change, immediately: - Suggest reviewing `proposal.md` and `tasks.md` - Wait for user confirmation before applying +### Step 5: After Implementation—Verify, Validate, and Sync Backlog + +**After each code modification (at the end of implementation):** + +1. **Verify:** + - Run quality gates: `hatch run format`, `hatch run type-check`, `hatch run contract-test`, `hatch test` (or `hatch run smart-test`). + - Ensure all tests pass and contracts are satisfied. + +2. **Validate the change:** + - Run `openspec validate --strict`. + - Optionally run `/wf-validate-change ` for breaking-change and dependency audit. + - If validation fails, fix proposal/specs/design/tasks and re-validate before considering the change complete. + +3. **Sync backlog (GitHub issues and Source Tracking):** + - **If the change targets a public repo** (e.g. specfact-cli, platform-frontend): + - **If no GitHub issue exists yet:** Create the issue per config.yaml (title `[Change] `, labels `enhancement` and `change-proposal`, body from proposal). Update `proposal.md` Source Tracking section with issue number, URL, repository, and status. + - **If an issue already exists:** Sync the issue with the change (e.g. update issue body/status from proposal, ensure Development link to branch/PR). Update `proposal.md` Source Tracking section with current status (e.g. "Last Synced Status: in-progress" or "done"). + - Ensure backlog and code stay in sync: proposal Source Tracking and the GitHub issue reflect the current state of the change. + ## Implementation Pattern **Example workflow:** -``` +```text User: "Add a new command to list all backlog items" AI (automatically): -1. Detects: "Add" → triggers OpenSpec workflow -2. Searches: `openspec list` → no related changes found -3. Creates: `/openspec-proposal` (for ad-hoc changes) - - Asks for clarifications if needed - - Creates change proposal - - Validates change -4. Verifies: Shows change summary -5. Applies: `/specfact-cli-internal/wf-apply-change ` - - Implements the change +1. Reads openspec/config.yaml (project context and per-artifact rules). Does not modify code yet. +2. Detects: "Add" → triggers OpenSpec workflow +3. Searches: openspec list → no related changes found +4. Creates: /opsx-explore then /opsx-new (or /opsx:ff) or /wf-create-change-from-plan + - Applies config.yaml rules to all artifacts + - Creates change proposal, spec deltas, tasks + - Validates: openspec validate --strict +5. Verifies: Shows change summary; "Proceed with implementation?" +6. Applies: /opsx:apply (or /wf-apply-change ) + - Implements the change (TDD: tests first, then code) - Updates tasks - - Completes workflow +7. After implementation: Verify (quality gates), validate (openspec validate), sync backlog + - Create or update GitHub issue if public repo; update proposal Source Tracking ``` ## Error Handling - **If `openspec` command not found:** - - Inform user: "OpenSpec CLI not available. Proceeding with direct implementation." - - Skip OpenSpec workflow, implement directly + - Inform user: "OpenSpec CLI not available. No code modification will be made until an OpenSpec change exists (create one manually or install OpenSpec CLI)." + - Do not modify application code unless the user explicitly confirms: "Proceed without OpenSpec" or similar. -- **If specfact-cli-internal workspace not accessible:** - - Inform user: "Cannot access OpenSpec workspace. Proceeding with direct implementation." - - Skip OpenSpec workflow, implement directly +- **If specfact-cli workspace or openspec/ directory not accessible:** + - Inform user: "Cannot access OpenSpec workspace. No code modification will be made until a change exists." + - Do not modify application code unless the user explicitly confirms to proceed without OpenSpec. - **If change validation fails:** - - Fix validation errors + - Fix validation errors in proposal, specs, design, or tasks - Re-validate until passing - - Do not proceed with implementation until validation passes + - Do not proceed with implementation until validation passes (or user explicitly overrides) - **If user explicitly requests to skip:** - Respect user request: "Skipping OpenSpec workflow as requested." @@ -227,6 +283,8 @@ This rule works alongside: ## Notes - This rule applies to the **specfact-cli** codebase specifically +- **Mandatory before any code modification:** Read and apply `openspec/config.yaml` (project context and per-artifact rules). Ensure an OpenSpec change (new or delta) exists and is validated. No code change without a corresponding change proposal unless the user explicitly opts out. +- **Mandatory after each implementation:** Verify (quality gates), validate (`openspec validate --strict`), and sync backlog (create or update GitHub issue, update proposal Source Tracking) so backlog and code stay in sync. - For other repositories, this rule may not apply (check repository-specific rules) - **Important workspace distinction:** - **OpenSpec changes** are stored in `specfact-cli/openspec/changes/` diff --git a/.cursorrules b/.cursorrules index e3817bcf..8fc36278 100644 --- a/.cursorrules +++ b/.cursorrules @@ -5,6 +5,7 @@ - When starting a new chat session, capture the current timestamp from the client system using the `run_terminal_cmd` tool with `date "+%Y-%m-%d %H:%M:%S %z"` to ensure accurate timestamps are used in logs, commits, and other time-sensitive operations. - When starting a new chat session, get familiar with the build and test guide (refer to `.cursor/rules/testing-and-build-guide.mdc`). - When starting a new task, first check the project overview and current status in `README.md` and `AGENTS.md`. +- **OpenSpec (before code)**: Before modifying application code, follow the OpenSpec workflow in `.cursor/rules/automatic-openspec-workflow.mdc`: read and apply `openspec/config.yaml`, ensure an OpenSpec change (new or delta) exists and is validated, then implement. Exception: only when the user explicitly says "skip openspec", "direct implementation", "simple fix", or similar. - **Branch Protection**: This repository has branch protection enabled for `dev` and `main` branches. All changes must be made via Pull Requests: - Create a feature branch: `git checkout -b feature/your-feature-name` - Create a bugfix branch: `git checkout -b bugfix/your-bugfix-name` diff --git a/CHANGELOG.md b/CHANGELOG.md index c0652953..1e3e58f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,20 @@ All notable changes to this project will be documented in this file. --- +## [0.26.17] - 2026-02-03 + +### Fixed (0.26.17) + +- **Daily standup exports: comment annotations** (fixes [#179](https://github.com/nold-ai/specfact-cli/issues/179)) + - **`--comments` / `--annotations`**: Include item descriptions and comment annotations in `--copilot-export` and + `--summarize`/`--summarize-to` outputs when the adapter supports `get_comments` (GitHub). + - **Docs**: Updated daily standup tutorial and guides to document the new flags and outputs. + +### Changed (0.26.17) + +- **Version**: Bumped to 0.26.17 for issue [#179](https://github.com/nold-ai/specfact-cli/issues/179) + +--- ## [0.26.16] - 2026-02-02 ### Added (0.26.16) diff --git a/docs/getting-started/tutorial-daily-standup-sprint-review.md b/docs/getting-started/tutorial-daily-standup-sprint-review.md index edd6e502..d5da5853 100644 --- a/docs/getting-started/tutorial-daily-standup-sprint-review.md +++ b/docs/getting-started/tutorial-daily-standup-sprint-review.md @@ -20,8 +20,12 @@ This tutorial walks you through a complete **daily standup and sprint review** w - Use **`.specfact/backlog.yaml`** or environment variables when you're not in the repo (e.g. CI) or to override - **Post a standup comment** to the first (or selected) item with `--yesterday`, `--today`, `--blockers` and `--post` - Use **`--interactive`** for step-by-step story review (arrow-key selection, full detail, **existing comments on each issue** when the adapter supports them) -- Use **`--copilot-export `** to write a Markdown summary for Copilot slash-command during standup -- Use **`--summarize`** or **`--summarize-to `** to output a **prompt** (instruction + filter context + standup data) for a slash command (e.g. `specfact.daily`) or copy-paste to Copilot to **generate a standup summary** +- Use **`--copilot-export `** to write a Markdown summary for Copilot slash-command during standup; + add **`--comments`** (alias **`--annotations`**) to include descriptions and comment annotations when + the adapter supports fetching comments +- Use **`--summarize`** or **`--summarize-to `** to output a **prompt** (instruction + filter context + + standup data) for a slash command (e.g. `specfact.daily`) or copy-paste to Copilot to **generate a + standup summary**; add **`--comments`**/**`--annotations`** to include comment annotations in the prompt - Use the **`specfact.backlog-daily`** (or `specfact.daily`) slash prompt for interactive walkthrough with the DevOps team story-by-story (focus, issues, open questions, discussion notes as comments) - Filter by **`--assignee`**, **`--sprint`** / **`--iteration`**, **`--blockers-first`**, and optional **`--suggest-next`** @@ -121,10 +125,13 @@ Use **`--suggest-next`** to show a suggested next item by value score (business To feed a **summary file** into your AI IDE (e.g. for a Copilot slash-command during standup): ```bash -specfact backlog daily github --copilot-export ./standup-summary.md +specfact backlog daily github --copilot-export ./standup-summary.md --comments ``` -The file contains one section per item (ID, title, status, assignees, last updated, progress, blockers). You can open it in your IDE and use it with Copilot. Same scope as the standup table (state, assignee, limit, etc.). +The file contains one section per item (ID, title, status, assignees, last updated, progress, blockers). +With `--comments`/`--annotations`, it also includes the item description and comment annotations when the +adapter supports fetching comments. You can open it in your IDE and use it with Copilot. Same scope as +the standup table (state, assignee, limit, etc.). --- @@ -134,13 +141,17 @@ To get a **prompt** you can paste into Copilot or feed to a slash command (e.g. ```bash # Print prompt to stdout (copy-paste to Copilot) -specfact backlog daily github --summarize +specfact backlog daily github --summarize --comments # Write prompt to a file (e.g. for slash command) -specfact backlog daily github --summarize-to ./standup-prompt.md +specfact backlog daily github --summarize-to ./standup-prompt.md --comments ``` -The output includes an instruction to generate a standup summary, the applied filter context (adapter, state, sprint, assignee, limit), and the same per-item data as `--copilot-export`. Use it with the **`specfact.backlog-daily`** slash prompt for interactive team walkthrough (story-by-story, current focus, issues/open questions, discussion notes as comments). +The output includes an instruction to generate a standup summary, the applied filter context (adapter, +state, sprint, assignee, limit), and the same per-item data as `--copilot-export`. With +`--comments`/`--annotations`, the prompt includes comment annotations when supported. Use it with the +**`specfact.backlog-daily`** slash prompt for interactive team walkthrough (story-by-story, current focus, +issues/open questions, discussion notes as comments). --- @@ -187,8 +198,8 @@ The output includes an instruction to generate a standup summary, the applied fi | Override or use outside repo | Use `.specfact/backlog.yaml`, env vars (`SPECFACT_GITHUB_REPO_OWNER`, etc.), or CLI `--repo-owner`/`--repo-name` or `--ado-org`/`--ado-project`. | | Post standup to first item | Use `--yesterday "..."` `--today "..."` `--blockers "..."` and `--post` (values required). | | Step through stories with full detail (including issue comments) | Use `--interactive`; optionally `--suggest-next`. | -| Feed standup into Copilot | Use `--copilot-export `. | -| Generate standup summary via AI (slash command or Copilot) | Use `--summarize` (stdout) or `--summarize-to `; use with `specfact.backlog-daily` slash prompt. | +| Feed standup into Copilot | Use `--copilot-export `; add `--comments`/`--annotations` for comment annotations. | +| Generate standup summary via AI (slash command or Copilot) | Use `--summarize` (stdout) or `--summarize-to `; add `--comments`/`--annotations` for comment annotations; use with `specfact.backlog-daily` slash prompt. | --- diff --git a/docs/guides/agile-scrum-workflows.md b/docs/guides/agile-scrum-workflows.md index 0a6f2139..e70940d4 100644 --- a/docs/guides/agile-scrum-workflows.md +++ b/docs/guides/agile-scrum-workflows.md @@ -14,7 +14,29 @@ SpecFact CLI supports real-world agile/scrum practices through: - **Definition of Ready (DoR)**: Automatic validation of story readiness for sprint planning - **Backlog Refinement** 🆕: AI-assisted template-driven refinement for standardizing work items from DevOps backlogs -- **Daily Standup**: Use `specfact backlog daily ` to list my/filtered items with status and last activity. Default scope (state=open, limit=20, optional assignee=me) is applied when not overridden; configure via `SPECFACT_STANDUP_STATE`, `SPECFACT_STANDUP_LIMIT`, `SPECFACT_STANDUP_ASSIGNEE` or `.specfact/standup.yaml`. Use `--iteration` / `--sprint` (e.g. `--sprint current`) to focus on current iteration when the adapter supports it; sprint/iteration end date is shown when provided by adapter or config (`standup.sprint_end_date`). A second table **Pending / open for commitment** lists unassigned items (same scope); use `--show-unassigned`/`--no-show-unassigned` or `--unassigned-only`. Use `--blockers-first` to sort items with blockers first; enable `show_priority` or `show_value` in standup config for optional priority/value column (value-driven/SAFe). Optional standup summary (yesterday/today/blockers) from item body; optionally post standup comment to linked issue via `--post` when the adapter supports comments (e.g. GitHub). **Interactive step-by-step review**: Use `--interactive` to select stories with arrow keys (questionary) and view full detail (refine-like: description, acceptance criteria, standup fields, comments when adapter supports); navigate with Next/Previous/Back to list/Exit. Use `--suggest-next` to show suggested next item by value score (business_value / (story_points × priority)). **Copilot export**: Use `--copilot-export ` to write a summarized Markdown file of each story for use with Copilot slash-command during standup (complementary aid, not replacement for backlog). **Kanban**: omit iteration/sprint and use state + limit; unassigned = pullable work. **Scrum/SAFe**: use `--sprint current` and optional priority/value. **Out of scope**: Sprint goal is in your board/sprint settings (not displayed by CLI). Stale/at-risk flags (e.g. "no update in N days") are not in scope—use last updated + blockers. Structured "blocked by" (link to another issue) is not in scope; only free-text blockers are supported. +- **Daily Standup**: Use `specfact backlog daily ` to list my/filtered items with status and last activity. + Default scope (state=open, limit=20, optional assignee=me) is applied when not overridden; configure via + `SPECFACT_STANDUP_STATE`, `SPECFACT_STANDUP_LIMIT`, `SPECFACT_STANDUP_ASSIGNEE` or + `.specfact/standup.yaml`. Use `--iteration` / `--sprint` (e.g. `--sprint current`) to focus on current + iteration when the adapter supports it; sprint/iteration end date is shown when provided by adapter or + config (`standup.sprint_end_date`). A second table **Pending / open for commitment** lists unassigned + items (same scope); use `--show-unassigned`/`--no-show-unassigned` or `--unassigned-only`. Use + `--blockers-first` to sort items with blockers first; enable `show_priority` or `show_value` in standup + config for optional priority/value column (value-driven/SAFe). Optional standup summary + (yesterday/today/blockers) from item body; optionally post standup comment to linked issue via `--post` + when the adapter supports comments (e.g. GitHub). + **Interactive step-by-step review**: Use `--interactive` to select stories with arrow keys (questionary) + and view full detail (refine-like: description, acceptance criteria, standup fields, comments when adapter + supports); navigate with Next/Previous/Back to list/Exit. Use `--suggest-next` to show suggested next + item by value score (business_value / (story_points × priority)). + **Copilot export**: Use `--copilot-export ` to write a summarized Markdown file of each story for + Copilot. Add `--comments` (alias `--annotations`) to include descriptions and comment annotations in + `--copilot-export` and `--summarize` outputs when the adapter supports `get_comments` (GitHub). + **Kanban**: omit iteration/sprint and use state + limit; unassigned = pullable work. **Scrum/SAFe**: use + `--sprint current` and optional priority/value. **Out of scope**: Sprint goal is in your board/sprint + settings (not displayed by CLI). Stale/at-risk flags (e.g. "no update in N days") are not in scope—use + last updated + blockers. Structured "blocked by" (link to another issue) is not in scope; only free-text + blockers are supported. - **Dependency Management**: Track story-to-story and feature-to-feature dependencies - **Prioritization**: Priority levels, ranking, and business value scoring - **Sprint Planning**: Target sprint/release assignment and story point tracking @@ -56,13 +78,19 @@ specfact backlog daily github \ # 4. Optional: interactive step-through, Copilot export, or standup summary prompt specfact backlog daily github --interactive # step-through; detail view shows existing comments on each issue # or -specfact backlog daily github --copilot-export ./standup.md +specfact backlog daily github --copilot-export ./standup.md --comments # or -specfact backlog daily github --summarize # prompt to stdout for AI to generate standup summary +specfact backlog daily github --summarize --comments # prompt to stdout for AI to generate standup summary specfact backlog daily github --summarize-to ./standup-prompt.md ``` -Use the **`specfact.backlog-daily`** (or `specfact.daily`) slash prompt for interactive walkthrough with the DevOps team story-by-story (current focus, issues/open questions, discussion notes as comments). Default scope: **state=open**, **limit=20**; configure via `SPECFACT_STANDUP_*` or `.specfact/standup.yaml`. Use `--assignee me`, `--sprint current`, `--blockers-first`, `--interactive`, `--suggest-next`, `--copilot-export `, `--summarize`, and `--summarize-to ` as needed. See [Tutorial: Daily Standup and Sprint Review](../getting-started/tutorial-daily-standup-sprint-review.md) for the full walkthrough. +Use the **`specfact.backlog-daily`** (or `specfact.daily`) slash prompt for interactive walkthrough with the +DevOps team story-by-story (current focus, issues/open questions, discussion notes as comments). Default +scope: **state=open**, **limit=20**; configure via `SPECFACT_STANDUP_*` or `.specfact/standup.yaml`. Use +`--assignee me`, `--sprint current`, `--blockers-first`, `--interactive`, `--suggest-next`, +`--copilot-export `, `--summarize`, `--summarize-to `, and `--comments`/`--annotations` as +needed. See [Tutorial: Daily Standup and Sprint Review](../getting-started/tutorial-daily-standup-sprint-review.md) +for the full walkthrough. ## Persona-Based Workflows diff --git a/docs/guides/devops-adapter-integration.md b/docs/guides/devops-adapter-integration.md index e29dbfaf..63bf15a3 100644 --- a/docs/guides/devops-adapter-integration.md +++ b/docs/guides/devops-adapter-integration.md @@ -19,7 +19,26 @@ SpecFact CLI supports **bidirectional synchronization** between OpenSpec change - **Issue Creation**: Export OpenSpec change proposals as GitHub Issues (or other DevOps backlog items) - **Progress Tracking**: Automatically detect code changes and add progress comments to issues -- **Standup Comments**: Use `specfact backlog daily --post` with `--yesterday`, `--today`, `--blockers` to post a standup summary as a comment on the linked issue (GitHub/ADO adapters that support comments). Standup config: set defaults via env (`SPECFACT_STANDUP_STATE`, `SPECFACT_STANDUP_LIMIT`, `SPECFACT_STANDUP_ASSIGNEE`, `SPECFACT_STANDUP_SPRINT_END`) or optional `.specfact/standup.yaml` (e.g. `default_state`, `limit`, `sprint`, `show_priority`, `suggest_next`). Iteration/sprint and sprint end date support depend on the adapter (ADO supports current iteration and iteration path; see adapter docs). Use `--blockers-first` and config `show_priority`/`show_value` for time-critical and value-driven standups. **Interactive review** (`--interactive`): step-through stories with arrow-key selection; detail view shows **existing comments annotated to each issue** when the adapter implements `get_comments(item)` (GitHub adapter supports it). **Value score / suggested next**: when BacklogItem has `story_points`, `business_value`, and `priority`, use `--suggest-next` or config `suggest_next` to show suggested next item (business_value / (story_points × priority)). **Standup summary prompt** (`--summarize` or `--summarize-to PATH`): output a prompt (instruction + filter context + standup data) for slash command or Copilot to generate a standup summary. **Slash prompt** `specfact.backlog-daily` (or `specfact.daily`): use with IDE/Copilot for interactive team walkthrough story-by-story (current focus, issues/open questions, discussion notes as comments); prompt file at `resources/prompts/specfact.backlog-daily.md`. **Sprint goal** is stored in your board/sprint settings and is not displayed or edited by the CLI. +- **Standup Comments**: Use `specfact backlog daily --post` with `--yesterday`, `--today`, `--blockers` to post + a standup summary as a comment on the linked issue (GitHub/ADO adapters that support comments). Standup + config: set defaults via env (`SPECFACT_STANDUP_STATE`, `SPECFACT_STANDUP_LIMIT`, + `SPECFACT_STANDUP_ASSIGNEE`, `SPECFACT_STANDUP_SPRINT_END`) or optional `.specfact/standup.yaml` + (e.g. `default_state`, `limit`, `sprint`, `show_priority`, `suggest_next`). Iteration/sprint and sprint + end date support depend on the adapter (ADO supports current iteration and iteration path; see adapter + docs). Use `--blockers-first` and config `show_priority`/`show_value` for time-critical and value-driven + standups. **Interactive review** (`--interactive`): step-through stories with arrow-key selection; detail + view shows **existing comments annotated to each issue** when the adapter implements `get_comments(item)` + (GitHub adapter supports it). **Comment annotations in exports**: add `--comments` (alias + `--annotations`) to include descriptions and comment annotations in `--copilot-export` and + `--summarize`/`--summarize-to` outputs when the adapter supports fetching comments. **Value score / + suggested next**: when BacklogItem has `story_points`, `business_value`, and `priority`, use + `--suggest-next` or config `suggest_next` to show suggested next item (business_value / (story_points × + priority)). **Standup summary prompt** (`--summarize` or `--summarize-to PATH`): output a prompt + (instruction + filter context + standup data) for slash command or Copilot to generate a standup summary. + **Slash prompt** `specfact.backlog-daily` (or `specfact.daily`): use with IDE/Copilot for interactive + team walkthrough story-by-story (current focus, issues/open questions, discussion notes as comments); + prompt file at `resources/prompts/specfact.backlog-daily.md`. **Sprint goal** is stored in your + board/sprint settings and is not displayed or edited by the CLI. - **Content Sanitization**: Protect internal information when syncing to public repositories - **Separate Repository Support**: Handle cases where OpenSpec proposals and source code are in different repositories diff --git a/openspec/CHANGE_ORDER.md b/openspec/CHANGE_ORDER.md new file mode 100644 index 00000000..a3c41512 --- /dev/null +++ b/openspec/CHANGE_ORDER.md @@ -0,0 +1,65 @@ +# OpenSpec change order by command and implementation dependency + +Changes are grouped by **main CLI command** and prefixed with **command-NN-** (double-digit order) so implementation order is explicit. Implement **01** before **02** within each command; cross-command dependencies are listed under "Blocked by" below. + +## Naming convention + +- **Folder**: `--` (e.g. `backlog-01-add-backlog-dependency-analysis-and-commands`). +- **Order**: 01, 02, … within the command group; lower numbers are implemented first where dependencies require it. + +## Command groups and change folders + +| Command | Order | Change folder (new name) | GitHub # | Blocked by | +|----------|-------|---------------------------|----------|------------| +| policy | 01 | policy-01-unify-policies-engine | 176 | — | +| patch | 01 | patch-01-patch-mode-preview-apply | 177 | #176 | +| backlog | 01 | backlog-01-add-backlog-dependency-analysis-and-commands | 116 | — | +| backlog | 02 | backlog-02-add-backlog-add-interactive-issue-creation | 173 | #116 | +| backlog | 03 | backlog-03-daily-standup-exceptions-first | 175 | #176, #177 | +| backlog | 04 | backlog-04-sprint-planning-capacity-commitment-support | 170 | — | +| backlog | 05 | backlog-05-story-complexity-splitting-hints-support | 171 | — | +| backlog | 06 | backlog-06-kanban-flow-metrics | 183 | #116, #176 | +| backlog | 07 | backlog-07-safe-pi-planning | 184 | #116, #176 | +| backlog | 08 | backlog-08-risk-rollups | 182 | #116, #176, #170, #171 | +| backlog | 09 | backlog-09-definition-of-done-support | 169 | — (optional: #176) | +| ceremony | 01 | ceremony-01-ceremony-cockpit | 185 | #175, #170, #176 (optional: #183, #184) | +| validation | 01 | validation-01-add-thorough-codebase-validation | 163 | — | +| sidecar | 01 | sidecar-01-add-sidecar-flask-support | 102 | — | +| bundle | 01 | bundle-01-add-bundle-mapping-strategy | 121 | — | + +## GitHub "Blocked by" relationships + +Set these in GitHub so issue dependencies are explicit: + +1. **Issue #177** (patch-mode): **Blocked by** #176 +2. **Issue #173** (backlog add): **Blocked by** #116 +3. **Issue #175** (daily standup E1): **Blocked by** #176, #177 +4. **Issue #183** (kanban flow): **Blocked by** #116, #176 +5. **Issue #184** (safe PI): **Blocked by** #116, #176 +6. **Issue #182** (risk rollups): **Blocked by** #116, #176, #170, #171 +7. **Issue #185** (ceremony cockpit): **Blocked by** #175, #170, #176 + +**How to set in GitHub**: Open the issue (e.g. ) → right sidebar **Relationships** → **Mark as blocked by** → search and select the blocking issue(s). Repeat for each issue in the table above that has blockers. + +## Parent issues (Epics) per command + +One parent issue per main command for grouping. **Do not add an Epic label** — the project **Type** property already defines Epic (and other issue types). Set Type to Epic for these parent issues in the project board. Link child/change issues via **Relationships** (e.g. sub-issues or "tracks") or by setting the project **Parent** field to the epic. + +| Command / area | Parent issue | GitHub # | +|----------------|-------------|----------| +| `specfact backlog` | [Epic] specfact backlog | [#186](https://github.com/nold-ai/specfact-cli/issues/186) | +| `specfact policy` | [Epic] specfact policy | [#187](https://github.com/nold-ai/specfact-cli/issues/187) | +| Patch mode | [Epic] Patch mode (preview/apply) | [#188](https://github.com/nold-ai/specfact-cli/issues/188) | +| `specfact ceremony` | [Epic] specfact ceremony | [#189](https://github.com/nold-ai/specfact-cli/issues/189) | +| Thorough validation | [Epic] Thorough codebase validation | [#190](https://github.com/nold-ai/specfact-cli/issues/190) | +| Sidecar validation | [Epic] Sidecar validation | [#191](https://github.com/nold-ai/specfact-cli/issues/191) | +| Bundle mapping | [Epic] Bundle/spec mapping | [#192](https://github.com/nold-ai/specfact-cli/issues/192) | + +**Linking child issues**: On each change issue (e.g. #116, #173, #175, …), use the project **Type** and **Parent** (or GitHub Relationships) to associate it with the epic above. Type (Epic, Feature, Story, etc.) is set via the project **Type** property only; do not use an Epic or other type label. + +## Suggested implementation waves + +- **Wave 1 (foundation)**: policy-01, backlog-01 +- **Wave 2**: patch-01, backlog-02, backlog-04, backlog-05, backlog-09, validation-01, sidecar-01, bundle-01 +- **Wave 3**: backlog-03 (needs policy-01 + patch-01), backlog-06, backlog-07, backlog-08 +- **Wave 4**: ceremony-01 (after backlog-03, backlog-04, policy-01) diff --git a/openspec/changes/add-backlog-dependency-analysis-and-commands/CHANGE_VALIDATION.md b/openspec/changes/backlog-01-add-backlog-dependency-analysis-and-commands/CHANGE_VALIDATION.md similarity index 100% rename from openspec/changes/add-backlog-dependency-analysis-and-commands/CHANGE_VALIDATION.md rename to openspec/changes/backlog-01-add-backlog-dependency-analysis-and-commands/CHANGE_VALIDATION.md diff --git a/openspec/changes/add-backlog-dependency-analysis-and-commands/proposal.md b/openspec/changes/backlog-01-add-backlog-dependency-analysis-and-commands/proposal.md similarity index 100% rename from openspec/changes/add-backlog-dependency-analysis-and-commands/proposal.md rename to openspec/changes/backlog-01-add-backlog-dependency-analysis-and-commands/proposal.md diff --git a/openspec/changes/add-backlog-dependency-analysis-and-commands/specs/bridge-adapter/spec.md b/openspec/changes/backlog-01-add-backlog-dependency-analysis-and-commands/specs/bridge-adapter/spec.md similarity index 100% rename from openspec/changes/add-backlog-dependency-analysis-and-commands/specs/bridge-adapter/spec.md rename to openspec/changes/backlog-01-add-backlog-dependency-analysis-and-commands/specs/bridge-adapter/spec.md diff --git a/openspec/changes/add-backlog-dependency-analysis-and-commands/specs/devops-sync/spec.md b/openspec/changes/backlog-01-add-backlog-dependency-analysis-and-commands/specs/devops-sync/spec.md similarity index 100% rename from openspec/changes/add-backlog-dependency-analysis-and-commands/specs/devops-sync/spec.md rename to openspec/changes/backlog-01-add-backlog-dependency-analysis-and-commands/specs/devops-sync/spec.md diff --git a/openspec/changes/add-backlog-dependency-analysis-and-commands/tasks.md b/openspec/changes/backlog-01-add-backlog-dependency-analysis-and-commands/tasks.md similarity index 96% rename from openspec/changes/add-backlog-dependency-analysis-and-commands/tasks.md rename to openspec/changes/backlog-01-add-backlog-dependency-analysis-and-commands/tasks.md index 2a00c689..af2f7c01 100644 --- a/openspec/changes/add-backlog-dependency-analysis-and-commands/tasks.md +++ b/openspec/changes/backlog-01-add-backlog-dependency-analysis-and-commands/tasks.md @@ -257,9 +257,9 @@ ## 4. Git Workflow -- [ ] 4.1 Create git branch `feature/add-backlog-dependency-analysis-and-commands` from `dev` branch +- [ ] 4.1 Create git branch `feature/backlog-01-backlog-01-add-backlog-dependency-analysis-and-commands` from `dev` branch - [ ] 4.1.1 Ensure we're on dev and up to date: `git checkout dev && git pull origin dev` - - [ ] 4.1.2 Create branch: `git checkout -b feature/add-backlog-dependency-analysis-and-commands` + - [ ] 4.1.2 Create branch: `git checkout -b feature/backlog-01-backlog-01-add-backlog-dependency-analysis-and-commands` - [ ] 4.1.3 Verify branch was created: `git branch --show-current` ## 5. Documentation @@ -277,7 +277,7 @@ - [ ] 6.1 Prepare changes for commit - [ ] 6.1.1 Ensure all changes are committed: `git add .` - [ ] 6.1.2 Commit with conventional message: `git commit -m "feat: add backlog dependency analysis and command suites"` - - [ ] 6.1.3 Push to remote: `git push origin feature/add-backlog-dependency-analysis-and-commands` -- [ ] 6.2 Create Pull Request from `feature/add-backlog-dependency-analysis-and-commands` to `dev` branch - - [ ] 6.2.1 Create PR using GitHub CLI: `gh pr create --base dev --head feature/add-backlog-dependency-analysis-and-commands --title "feat: add backlog dependency analysis and command suites" --body "Implements OpenSpec change proposal: add-backlog-dependency-analysis-and-commands"` + - [ ] 6.1.3 Push to remote: `git push origin feature/backlog-01-backlog-01-add-backlog-dependency-analysis-and-commands` +- [ ] 6.2 Create Pull Request from `feature/backlog-01-backlog-01-add-backlog-dependency-analysis-and-commands` to `dev` branch + - [ ] 6.2.1 Create PR using GitHub CLI: `gh pr create --base dev --head feature/backlog-01-backlog-01-add-backlog-dependency-analysis-and-commands --title "feat: add backlog dependency analysis and command suites" --body "Implements OpenSpec change proposal: backlog-01-add-backlog-dependency-analysis-and-commands"` - [ ] 6.2.2 Verify PR was created and is visible on GitHub diff --git a/openspec/changes/add-backlog-add-interactive-issue-creation/CHANGE_VALIDATION.md b/openspec/changes/backlog-02-add-backlog-add-interactive-issue-creation/CHANGE_VALIDATION.md similarity index 100% rename from openspec/changes/add-backlog-add-interactive-issue-creation/CHANGE_VALIDATION.md rename to openspec/changes/backlog-02-add-backlog-add-interactive-issue-creation/CHANGE_VALIDATION.md diff --git a/openspec/changes/add-backlog-add-interactive-issue-creation/design.md b/openspec/changes/backlog-02-add-backlog-add-interactive-issue-creation/design.md similarity index 100% rename from openspec/changes/add-backlog-add-interactive-issue-creation/design.md rename to openspec/changes/backlog-02-add-backlog-add-interactive-issue-creation/design.md diff --git a/openspec/changes/add-backlog-add-interactive-issue-creation/proposal.md b/openspec/changes/backlog-02-add-backlog-add-interactive-issue-creation/proposal.md similarity index 77% rename from openspec/changes/add-backlog-add-interactive-issue-creation/proposal.md rename to openspec/changes/backlog-02-add-backlog-add-interactive-issue-creation/proposal.md index e3575397..15a59b35 100644 --- a/openspec/changes/add-backlog-add-interactive-issue-creation/proposal.md +++ b/openspec/changes/backlog-02-add-backlog-add-interactive-issue-creation/proposal.md @@ -6,10 +6,12 @@ After implementing backlog adapters and dependency analysis (add-backlog-depende ## What Changes -- **NEW**: Add CLI command `specfact backlog add` (or alias `specfact backlog add-issue`) for interactive creation of backlog issues (epic, feature, story, task, bug, spike) with optional parent, title, body, and DoR validation. +- **NEW**: Add CLI command `specfact backlog add` (or alias `specfact backlog add-issue`) for interactive creation of backlog issues (epic, feature, story, task, bug, spike) with optional parent, title, body, DoR validation, and optional `--sprint` to assign new issue to sprint (when provider supports it). - **NEW**: Support multiple backlog levels (epic, feature, story, task, bug, spike, custom) with configurable creation hierarchy (allowed parent types per child type) via template or backlog_config; default derived from existing type_mapping and dependency_rules. - **NEW**: Extend `BacklogAdapterMixin` with abstract method `create_issue(project_id: str, payload: dict) -> dict` returning created item (id, key, url); implement in GitHub and ADO adapters with unified payload shape and provider-specific mapping. -- **NEW**: Add spec delta and implementation for add flow: load graph (BacklogGraphBuilder, fetch_all_issues, fetch_relationships), resolve type and parent from template/hierarchy, validate parent exists and allowed type, optional DoR check (reuse backlog refine DoR), map draft to provider payload, call adapter create_issue, output created id/key/url. +- **NEW**: Add spec delta and implementation for add flow: load graph (BacklogGraphBuilder, fetch_all_issues, fetch_relationships), resolve type and parent from template/hierarchy, validate parent exists and allowed type, optional DoR check (reuse backlog refine DoR; **use Policy Engine #176 for DoR enforcement when available**), map draft to provider payload, call adapter create_issue, output created id/key/url. +- **EXTEND**: **E5**: Provide draft patch preview before create (integrate with patch-mode-preview-apply #177 when available) so user can review proposed issue body/fields before creating. +- **EXTEND**: **E5**: When linking to existing issues (e.g. parent, blocks), support fuzzy match + user confirmation; no silent link (aligns with bundle mapping and future linking). - **EXTEND**: Template or backlog_config with optional creation_hierarchy (allowed parent types per child type) so Scrum/SAFe/Kanban and custom hierarchies work without code changes. - **EXTEND**: Documentation (agile-scrum-workflows, backlog-refinement) for backlog add workflow, interactive creation, DoR, and slash-prompt usage. @@ -19,10 +21,10 @@ After implementing backlog adapters and dependency analysis (add-backlog-depende ## Impact -- **Affected specs**: New `openspec/changes/add-backlog-add-interactive-issue-creation/specs/backlog-add/spec.md` (Given/When/Then for add flow, hierarchy, create via adapter). +- **Affected specs**: New `openspec/changes/backlog-02-add-backlog-add-interactive-issue-creation/specs/backlog-add/spec.md` (Given/When/Then for add flow, hierarchy, create via adapter). - **Affected code**: `src/specfact_cli/adapters/backlog_base.py` (abstract create_issue), `github.py` and `ado.py` (implement create_issue); `src/specfact_cli/commands/backlog_commands.py` or backlog command module (add `specfact backlog add` subcommand); optional creation_hierarchy loader and validation using BacklogGraphBuilder and DependencyAnalyzer (from add-backlog-dependency-analysis-and-commands when available). - **Affected documentation** (): docs/guides/agile-scrum-workflows.md, backlog-refinement or backlog guide for backlog add, interactive creation, DoR, slash prompt. -- **Integration points**: BacklogGraphBuilder, DependencyAnalyzer, fetch_all_issues, fetch_relationships (add-backlog-dependency-analysis-and-commands); DoR from backlog-refinement; templates and backlog_config. +- **Integration points**: BacklogGraphBuilder, DependencyAnalyzer, fetch_all_issues, fetch_relationships (add-backlog-dependency-analysis-and-commands); DoR from backlog-refinement; **Policy Engine (#176) for DoR enforcement**; **patch-mode-preview-apply (#177) for draft patch preview before create**; templates and backlog_config. - **Backward compatibility**: Additive only; new command and adapter method; existing refine/sync/analyze-deps unchanged. Depends on add-backlog-dependency-analysis-and-commands for graph/templates; can be implemented with minimal graph usage (e.g. fetch + validate parent) if that change is not yet merged. ## Source Tracking diff --git a/openspec/changes/add-backlog-add-interactive-issue-creation/specs/backlog-add/spec.md b/openspec/changes/backlog-02-add-backlog-add-interactive-issue-creation/specs/backlog-add/spec.md similarity index 79% rename from openspec/changes/add-backlog-add-interactive-issue-creation/specs/backlog-add/spec.md rename to openspec/changes/backlog-02-add-backlog-add-interactive-issue-creation/specs/backlog-add/spec.md index ff68a80d..4246fd9e 100644 --- a/openspec/changes/add-backlog-add-interactive-issue-creation/specs/backlog-add/spec.md +++ b/openspec/changes/backlog-02-add-backlog-add-interactive-issue-creation/specs/backlog-add/spec.md @@ -124,3 +124,37 @@ The system SHALL support configurable creation hierarchy (allowed parent types p - creation_hierarchy is optional; when absent, default or derived rules apply - Validation uses both existence of parent in graph and allowed type from hierarchy + +### Requirement: Optional sprint assignment and linking via fuzzy match (E5) + +The system SHALL support optional `--sprint ` so the created issue can be assigned to a sprint when the adapter and provider support it. When linking to existing issues (e.g. parent, blocks), the system SHALL support fuzzy match with user confirmation; no silent or automatic link creation. + +**Rationale**: 2026-01-30 plan value chain; E5—bundle mapping and future linking. + +#### Scenario: Add issue with optional sprint assignment + +**Given**: Adapter and provider support sprint assignment (e.g. GitHub Projects, ADO iteration) + +**When**: The user runs `specfact backlog add --type story --title "T" --sprint Sprint-1` + +**Then**: The system includes sprint assignment in the payload when creating the issue (when supported) + +**And**: When provider does not support sprint, the option is ignored or a clear message is shown + +**Acceptance Criteria**: + +- `--sprint` is optional; payload includes sprint when adapter supports it; no failure when unsupported. + +#### Scenario: Link to existing issue via fuzzy match + +**Given**: User specifies a parent or "blocks" target by partial key or title + +**When**: The system finds one or more candidate issues (fuzzy match) + +**Then**: The system presents candidates and requires user confirmation before creating the link + +**And**: No link is created without explicit user confirmation + +**Acceptance Criteria**: + +- Fuzzy match is used for discovery only; linking requires user confirmation; no silent writes. diff --git a/openspec/changes/add-backlog-add-interactive-issue-creation/tasks.md b/openspec/changes/backlog-02-add-backlog-add-interactive-issue-creation/tasks.md similarity index 90% rename from openspec/changes/add-backlog-add-interactive-issue-creation/tasks.md rename to openspec/changes/backlog-02-add-backlog-add-interactive-issue-creation/tasks.md index 0f20c6f1..ded592f9 100644 --- a/openspec/changes/add-backlog-add-interactive-issue-creation/tasks.md +++ b/openspec/changes/backlog-02-add-backlog-add-interactive-issue-creation/tasks.md @@ -15,8 +15,8 @@ Do not implement production code for new behavior until the corresponding tests ## 1. Create git branch from dev - [ ] 1.1 Ensure we're on dev and up to date: `git checkout dev && git pull origin dev` -- [ ] 1.2 Create branch with Development link to issue (if exists): `gh issue develop 173 --repo nold-ai/specfact-cli --name feature/add-backlog-add-interactive-issue-creation --checkout` -- [ ] 1.3 Or create branch without issue link: `git checkout -b feature/add-backlog-add-interactive-issue-creation` (if no issue yet) +- [ ] 1.2 Create branch with Development link to issue (if exists): `gh issue develop 173 --repo nold-ai/specfact-cli --name feature/backlog-02-add-backlog-add-interactive-issue-creation --checkout` +- [ ] 1.3 Or create branch without issue link: `git checkout -b feature/backlog-02-add-backlog-add-interactive-issue-creation` (if no issue yet) - [ ] 1.4 Verify branch was created: `git branch --show-current` ## 2. Create GitHub issue in nold-ai/specfact-cli (mandatory) @@ -75,6 +75,6 @@ Do not implement production code for new behavior until the corresponding tests ## 10. Create Pull Request to dev - [ ] 10.1 Ensure all changes are committed: `git add .` and `git commit -m "feat(backlog): add backlog add for interactive issue creation"` -- [ ] 10.2 Push to remote: `git push origin feature/add-backlog-add-interactive-issue-creation` -- [ ] 10.3 Create PR: `gh pr create --repo nold-ai/specfact-cli --base dev --head feature/add-backlog-add-interactive-issue-creation --title "feat(backlog): add backlog add for interactive issue creation" --body-file ` (use repo PR template; add OpenSpec change ID `add-backlog-add-interactive-issue-creation` and summary; reference GitHub issue with `Fixes nold-ai/specfact-cli#173`). +- [ ] 10.2 Push to remote: `git push origin feature/backlog-02-add-backlog-add-interactive-issue-creation` +- [ ] 10.3 Create PR: `gh pr create --repo nold-ai/specfact-cli --base dev --head feature/backlog-02-add-backlog-add-interactive-issue-creation --title "feat(backlog): add backlog add for interactive issue creation" --body-file ` (use repo PR template; add OpenSpec change ID `backlog-02-add-backlog-add-interactive-issue-creation` and summary; reference GitHub issue with `Fixes nold-ai/specfact-cli#173`). - [ ] 10.4 Verify PR and branch are linked to issue in Development section. diff --git a/openspec/changes/daily-standup-exceptions-first/CHANGE_VALIDATION.md b/openspec/changes/backlog-03-daily-standup-exceptions-first/CHANGE_VALIDATION.md similarity index 88% rename from openspec/changes/daily-standup-exceptions-first/CHANGE_VALIDATION.md rename to openspec/changes/backlog-03-daily-standup-exceptions-first/CHANGE_VALIDATION.md index 7b5ec68b..07600d54 100644 --- a/openspec/changes/daily-standup-exceptions-first/CHANGE_VALIDATION.md +++ b/openspec/changes/backlog-03-daily-standup-exceptions-first/CHANGE_VALIDATION.md @@ -1,6 +1,7 @@ # Change Validation Report: daily-standup-exceptions-first **Validation Date**: 2026-02-02 +**GitHub Issue**: [#175](https://github.com/nold-ai/specfact-cli/issues/175) (E1 delta) **Plan Reference**: specfact-cli-internal/docs/internal/implementation/2026-02-01-backlog-changes-improvement.md (E1) **Validation Method**: Plan alignment + OpenSpec strict validation @@ -9,7 +10,7 @@ - **Plan Delta (E1)**: New change extending archived daily-standup-progress-support with exceptions-first section order, `--mode scrum|kanban|safe`, patch integration. - **Breaking Changes**: 0 (additive; extends archived standup). - **Validation Result**: Pass. -- **OpenSpec Validation**: `openspec validate daily-standup-exceptions-first --strict` — valid. +- **OpenSpec Validation**: `openspec validate backlog-03-daily-standup-exceptions-first --strict` — valid. ## Alignment with Plan E1 diff --git a/openspec/changes/daily-standup-exceptions-first/proposal.md b/openspec/changes/backlog-03-daily-standup-exceptions-first/proposal.md similarity index 75% rename from openspec/changes/daily-standup-exceptions-first/proposal.md rename to openspec/changes/backlog-03-daily-standup-exceptions-first/proposal.md index d80b330b..475fbe5b 100644 --- a/openspec/changes/daily-standup-exceptions-first/proposal.md +++ b/openspec/changes/backlog-03-daily-standup-exceptions-first/proposal.md @@ -1,5 +1,7 @@ # Change: Daily standup exceptions-first and flow/policy hooks (E1 delta) +**GitHub issue**: [#175](https://github.com/nold-ai/specfact-cli/issues/175) — E1 delta; PRs must reference `Fixes nold-ai/specfact-cli#175`. + ## Why The archived change `daily-standup-progress-support` (#168) delivers standup view, interactive review, and Copilot export. Teams love tools that surface blockers and risks first. This delta extends standup with exceptions-first default section order, optional `--mode scrum|kanban|safe`, and integration with Policy Engine and patch mode so standup output highlights policy failures and aging/stalled work before normal status. @@ -17,7 +19,7 @@ The archived change `daily-standup-progress-support` (#168) delivers standup vie ## Impact -- **Affected specs**: New `openspec/changes/daily-standup-exceptions-first/specs/daily-standup/spec.md` (delta on daily-standup; Given/When/Then for exceptions-first order, mode, patch). +- **Affected specs**: New `openspec/changes/backlog-03-daily-standup-exceptions-first/specs/daily-standup/spec.md` (delta on daily-standup; Given/When/Then for exceptions-first order, mode, patch). - **Affected code**: `src/specfact_cli/commands/backlog_commands.py` (daily command: section order, --mode, patch hook); depends on unify-policies-engine and patch-mode-preview-apply when available. - **Affected documentation** (): docs/guides/agile-scrum-workflows.md, docs/guides/devops-adapter-integration.md. - **Integration points**: Archived daily-standup-progress-support; unify-policies-engine (Δ1); patch-mode-preview-apply (Δ2). @@ -25,7 +27,7 @@ The archived change `daily-standup-progress-support` (#168) delivers standup vie ## Source Tracking -- **GitHub Issue**: #175 -- **Issue URL**: +- **GitHub Issue**: [#175](https://github.com/nold-ai/specfact-cli/issues/175) - **Repository**: nold-ai/specfact-cli -- **Last Synced Status**: proposed +- **PR link**: PR body MUST include `Fixes nold-ai/specfact-cli#175` for Development linking. +- **Last Synced Status**: E1 scope tracked in this change; implement via branch linked to #175 and PR that closes #175. diff --git a/openspec/changes/daily-standup-exceptions-first/specs/daily-standup/spec.md b/openspec/changes/backlog-03-daily-standup-exceptions-first/specs/daily-standup/spec.md similarity index 100% rename from openspec/changes/daily-standup-exceptions-first/specs/daily-standup/spec.md rename to openspec/changes/backlog-03-daily-standup-exceptions-first/specs/daily-standup/spec.md diff --git a/openspec/changes/daily-standup-exceptions-first/tasks.md b/openspec/changes/backlog-03-daily-standup-exceptions-first/tasks.md similarity index 70% rename from openspec/changes/daily-standup-exceptions-first/tasks.md rename to openspec/changes/backlog-03-daily-standup-exceptions-first/tasks.md index 2b36fa1d..160b5016 100644 --- a/openspec/changes/daily-standup-exceptions-first/tasks.md +++ b/openspec/changes/backlog-03-daily-standup-exceptions-first/tasks.md @@ -4,16 +4,16 @@ Per `openspec/config.yaml`, **tests before code** apply to any task that adds or changes behavior. -1. **Spec deltas** define behavior in `openspec/changes/daily-standup-exceptions-first/specs/daily-standup/spec.md`. +1. **Spec deltas** define behavior in `openspec/changes/backlog-03-daily-standup-exceptions-first/specs/daily-standup/spec.md`. 2. **Tests second**: Write unit/integration tests from those scenarios; run tests and **expect failure**. 3. **Code last**: Implement until tests pass. --- -## 1. Create git branch from dev +## 1. Create git branch from dev (linked to issue #175) - [ ] 1.1 Ensure we're on dev and up to date: `git checkout dev && git pull origin dev` -- [ ] 1.2 Create branch: `git checkout -b feature/daily-standup-exceptions-first` +- [ ] 1.2 Create branch linked to #175: `gh issue develop 175 --repo nold-ai/specfact-cli --name feature/backlog-03-daily-standup-exceptions-first --checkout` (or `git checkout -b feature/backlog-03-daily-standup-exceptions-first` if no gh) - [ ] 1.3 Verify branch: `git branch --show-current` ## 2. Tests first (exceptions-first order, --mode, patch hook) @@ -37,5 +37,5 @@ Per `openspec/config.yaml`, **tests before code** apply to any task that adds or ## 5. Create Pull Request to dev -- [ ] 5.1 Commit and push: `git add .` then `git commit -m "feat(backlog): daily standup exceptions-first and --mode scrum|kanban|safe"` and `git push origin feature/daily-standup-exceptions-first` -- [ ] 5.2 Create PR to dev using repo PR template; reference this change ID. +- [ ] 5.1 Commit and push: `git add .` then `git commit -m "feat(backlog): daily standup exceptions-first and --mode scrum|kanban|safe (fixes #175)"` and `git push origin feature/backlog-03-daily-standup-exceptions-first` +- [ ] 5.2 Create PR to dev using repo PR template; PR body MUST include `Fixes nold-ai/specfact-cli#175` and this change ID for Development linking. diff --git a/openspec/changes/sprint-planning-capacity-commitment-support/CHANGE_VALIDATION.md b/openspec/changes/backlog-04-sprint-planning-capacity-commitment-support/CHANGE_VALIDATION.md similarity index 100% rename from openspec/changes/sprint-planning-capacity-commitment-support/CHANGE_VALIDATION.md rename to openspec/changes/backlog-04-sprint-planning-capacity-commitment-support/CHANGE_VALIDATION.md diff --git a/openspec/changes/sprint-planning-capacity-commitment-support/design.md b/openspec/changes/backlog-04-sprint-planning-capacity-commitment-support/design.md similarity index 100% rename from openspec/changes/sprint-planning-capacity-commitment-support/design.md rename to openspec/changes/backlog-04-sprint-planning-capacity-commitment-support/design.md diff --git a/openspec/changes/sprint-planning-capacity-commitment-support/proposal.md b/openspec/changes/backlog-04-sprint-planning-capacity-commitment-support/proposal.md similarity index 92% rename from openspec/changes/sprint-planning-capacity-commitment-support/proposal.md rename to openspec/changes/backlog-04-sprint-planning-capacity-commitment-support/proposal.md index ae9daafe..44291174 100644 --- a/openspec/changes/sprint-planning-capacity-commitment-support/proposal.md +++ b/openspec/changes/backlog-04-sprint-planning-capacity-commitment-support/proposal.md @@ -18,7 +18,7 @@ SpecFact CLI supports sprint/release assignment and story points at the backlog- ## Impact -- **Affected specs**: New `openspec/changes/sprint-planning-capacity-commitment-support/specs/sprint-planning/spec.md` (Given/When/Then for capacity config, commitment sum, over/under output). +- **Affected specs**: New `openspec/changes/backlog-04-sprint-planning-capacity-commitment-support/specs/sprint-planning/spec.md` (Given/When/Then for capacity config, commitment sum, over/under output). - **Affected code**: `src/specfact_cli/commands/backlog_commands.py` (sprint-summary subcommand or extend existing); `src/specfact_cli/` (models or config for sprint capacity, commitment aggregation). - **Affected documentation** (): docs/guides/agile-scrum-workflows.md, docs/guides/backlog-refinement.md for sprint planning. - **Integration points**: Existing backlog list/export; BacklogItem.sprint + story_points; adapter-agnostic (capacity from `.specfact/sprint_capacity.yaml` or similar). diff --git a/openspec/changes/sprint-planning-capacity-commitment-support/specs/sprint-planning/spec.md b/openspec/changes/backlog-04-sprint-planning-capacity-commitment-support/specs/sprint-planning/spec.md similarity index 100% rename from openspec/changes/sprint-planning-capacity-commitment-support/specs/sprint-planning/spec.md rename to openspec/changes/backlog-04-sprint-planning-capacity-commitment-support/specs/sprint-planning/spec.md diff --git a/openspec/changes/sprint-planning-capacity-commitment-support/tasks.md b/openspec/changes/backlog-04-sprint-planning-capacity-commitment-support/tasks.md similarity index 89% rename from openspec/changes/sprint-planning-capacity-commitment-support/tasks.md rename to openspec/changes/backlog-04-sprint-planning-capacity-commitment-support/tasks.md index 18656214..9b8e92d8 100644 --- a/openspec/changes/sprint-planning-capacity-commitment-support/tasks.md +++ b/openspec/changes/backlog-04-sprint-planning-capacity-commitment-support/tasks.md @@ -15,8 +15,8 @@ Do not implement production code for new behavior until the corresponding tests ## 1. Create git branch from dev - [ ] 1.1 Ensure we're on dev and up to date: `git checkout dev && git pull origin dev` -- [ ] 1.2 Create branch with Development link to issue (if exists): `gh issue develop 170 --repo nold-ai/specfact-cli --name feature/sprint-planning-capacity-commitment-support --checkout` -- [ ] 1.3 Or create branch without issue link: `git checkout -b feature/sprint-planning-capacity-commitment-support` (if no issue yet) +- [ ] 1.2 Create branch with Development link to issue (if exists): `gh issue develop 170 --repo nold-ai/specfact-cli --name feature/backlog-04-sprint-planning-capacity-commitment-support --checkout` +- [ ] 1.3 Or create branch without issue link: `git checkout -b feature/backlog-04-sprint-planning-capacity-commitment-support` (if no issue yet) - [ ] 1.4 Verify branch was created: `git branch --show-current` ## 2. Create GitHub issue in nold-ai/specfact-cli (mandatory) @@ -68,6 +68,6 @@ Do not implement production code for new behavior until the corresponding tests ## 9. Create Pull Request to dev - [ ] 9.1 Ensure all changes are committed: `git add .` and `git commit -m "feat(backlog): add sprint planning capacity and commitment support"` -- [ ] 9.2 Push to remote: `git push origin feature/sprint-planning-capacity-commitment-support` -- [ ] 9.3 Create PR: `gh pr create --repo nold-ai/specfact-cli --base dev --head feature/sprint-planning-capacity-commitment-support --title "feat(backlog): add sprint planning capacity and commitment support" --body-file ` (use repo PR template; add OpenSpec change ID `sprint-planning-capacity-commitment-support` and summary; reference GitHub issue with `Fixes nold-ai/specfact-cli#170`). +- [ ] 9.2 Push to remote: `git push origin feature/backlog-04-sprint-planning-capacity-commitment-support` +- [ ] 9.3 Create PR: `gh pr create --repo nold-ai/specfact-cli --base dev --head feature/backlog-04-sprint-planning-capacity-commitment-support --title "feat(backlog): add sprint planning capacity and commitment support" --body-file ` (use repo PR template; add OpenSpec change ID `backlog-04-sprint-planning-capacity-commitment-support` and summary; reference GitHub issue with `Fixes nold-ai/specfact-cli#170`). - [ ] 9.4 Verify PR and branch are linked to issue in Development section. diff --git a/openspec/changes/story-complexity-splitting-hints-support/CHANGE_VALIDATION.md b/openspec/changes/backlog-05-story-complexity-splitting-hints-support/CHANGE_VALIDATION.md similarity index 100% rename from openspec/changes/story-complexity-splitting-hints-support/CHANGE_VALIDATION.md rename to openspec/changes/backlog-05-story-complexity-splitting-hints-support/CHANGE_VALIDATION.md diff --git a/openspec/changes/story-complexity-splitting-hints-support/design.md b/openspec/changes/backlog-05-story-complexity-splitting-hints-support/design.md similarity index 100% rename from openspec/changes/story-complexity-splitting-hints-support/design.md rename to openspec/changes/backlog-05-story-complexity-splitting-hints-support/design.md diff --git a/openspec/changes/story-complexity-splitting-hints-support/proposal.md b/openspec/changes/backlog-05-story-complexity-splitting-hints-support/proposal.md similarity index 90% rename from openspec/changes/story-complexity-splitting-hints-support/proposal.md rename to openspec/changes/backlog-05-story-complexity-splitting-hints-support/proposal.md index 0ba2dfc2..815d6a09 100644 --- a/openspec/changes/story-complexity-splitting-hints-support/proposal.md +++ b/openspec/changes/backlog-05-story-complexity-splitting-hints-support/proposal.md @@ -18,7 +18,7 @@ The backlog-refinement spec (openspec/specs/backlog-refinement/spec.md) includes ## Impact -- **Affected specs**: New `openspec/changes/story-complexity-splitting-hints-support/specs/story-complexity/spec.md` (Given/When/Then for complexity score, needs splitting, splitting suggestion in refinement output); references main `openspec/specs/backlog-refinement/spec.md` Story Complexity Analysis. +- **Affected specs**: New `openspec/changes/backlog-05-story-complexity-splitting-hints-support/specs/story-complexity/spec.md` (Given/When/Then for complexity score, needs splitting, splitting suggestion in refinement output); references main `openspec/specs/backlog-refinement/spec.md` Story Complexity Analysis. - **Affected code**: `src/specfact_cli/commands/backlog_commands.py` (integrate complexity/splitting into refine); `src/specfact_cli/` (new or existing module for complexity score, splitting suggestion). - **Affected documentation** (): docs/guides/backlog-refinement.md for complexity and splitting hints. - **Integration points**: Existing `specfact backlog refine`; BacklogItem (story_points, business_value, acceptance_criteria); optional AI hint for split boundaries; provider-agnostic. diff --git a/openspec/changes/story-complexity-splitting-hints-support/specs/story-complexity/spec.md b/openspec/changes/backlog-05-story-complexity-splitting-hints-support/specs/story-complexity/spec.md similarity index 100% rename from openspec/changes/story-complexity-splitting-hints-support/specs/story-complexity/spec.md rename to openspec/changes/backlog-05-story-complexity-splitting-hints-support/specs/story-complexity/spec.md diff --git a/openspec/changes/story-complexity-splitting-hints-support/tasks.md b/openspec/changes/backlog-05-story-complexity-splitting-hints-support/tasks.md similarity index 89% rename from openspec/changes/story-complexity-splitting-hints-support/tasks.md rename to openspec/changes/backlog-05-story-complexity-splitting-hints-support/tasks.md index 06eb360a..de2ad956 100644 --- a/openspec/changes/story-complexity-splitting-hints-support/tasks.md +++ b/openspec/changes/backlog-05-story-complexity-splitting-hints-support/tasks.md @@ -15,8 +15,8 @@ Do not implement production code for new behavior until the corresponding tests ## 1. Create git branch from dev - [ ] 1.1 Ensure we're on dev and up to date: `git checkout dev && git pull origin dev` -- [ ] 1.2 Create branch with Development link to issue (if exists): `gh issue develop 171 --repo nold-ai/specfact-cli --name feature/story-complexity-splitting-hints-support --checkout` -- [ ] 1.3 Or create branch without issue link: `git checkout -b feature/story-complexity-splitting-hints-support` (if no issue yet) +- [ ] 1.2 Create branch with Development link to issue (if exists): `gh issue develop 171 --repo nold-ai/specfact-cli --name feature/backlog-05-story-complexity-splitting-hints-support --checkout` +- [ ] 1.3 Or create branch without issue link: `git checkout -b feature/backlog-05-story-complexity-splitting-hints-support` (if no issue yet) - [ ] 1.4 Verify branch was created: `git branch --show-current` ## 2. Create GitHub issue in nold-ai/specfact-cli (mandatory) @@ -66,6 +66,6 @@ Do not implement production code for new behavior until the corresponding tests ## 9. Create Pull Request to dev - [ ] 9.1 Ensure all changes are committed: `git add .` and `git commit -m "feat(backlog): add story complexity and splitting hints to refine"` -- [ ] 9.2 Push to remote: `git push origin feature/story-complexity-splitting-hints-support` -- [ ] 9.3 Create PR: `gh pr create --repo nold-ai/specfact-cli --base dev --head feature/story-complexity-splitting-hints-support --title "feat(backlog): add story complexity and splitting hints to refine" --body-file ` (use repo PR template; add OpenSpec change ID `story-complexity-splitting-hints-support` and summary; reference GitHub issue with `Fixes nold-ai/specfact-cli#171`). +- [ ] 9.2 Push to remote: `git push origin feature/backlog-05-story-complexity-splitting-hints-support` +- [ ] 9.3 Create PR: `gh pr create --repo nold-ai/specfact-cli --base dev --head feature/backlog-05-story-complexity-splitting-hints-support --title "feat(backlog): add story complexity and splitting hints to refine" --body-file ` (use repo PR template; add OpenSpec change ID `backlog-05-story-complexity-splitting-hints-support` and summary; reference GitHub issue with `Fixes nold-ai/specfact-cli#171`). - [ ] 9.4 Verify PR and branch are linked to issue in Development section. diff --git a/openspec/changes/backlog-06-kanban-flow-metrics/proposal.md b/openspec/changes/backlog-06-kanban-flow-metrics/proposal.md new file mode 100644 index 00000000..a856fef5 --- /dev/null +++ b/openspec/changes/backlog-06-kanban-flow-metrics/proposal.md @@ -0,0 +1,33 @@ +# Change: Kanban Flow Metrics + WIP/Aging Signals — Δ4 + +## Why + +Kanban teams won't use sprint-based commands. Today SpecFact has Policy Engine (#176) and dependency graph (#116), but no Kanban-native workflow: WIP limits, aging WIP, flow metrics (cycle time/throughput), blocked time. Without `backlog flow` and `.specfact/kanban.yaml`, Kanban teams see SpecFact as "Scrum-only." + +## What Changes + +- **NEW**: Add CLI command `specfact backlog flow` (or `backlog flow-metrics`) for Kanban flow view: WIP per column, aging WIP, cycle time/throughput (when data exists), blocked time. +- **NEW**: Config `.specfact/kanban.yaml` for WIP limits, column definitions, aging thresholds; integrate with Policy Engine (#176) for entry/exit policies. +- **NEW**: Output flow metrics (WIP, aging, cycle time, throughput) in machine-readable (JSON) and human-readable (Markdown) formats. +- **EXTEND**: Policy Engine (#176) supports Kanban entry/exit policies per column when kanban config is present. +- **EXTEND**: When `backlog daily` is run with `--mode kanban` and flow data exists, output MAY include a "flow exceptions" section (WIP/aging violations); integration with daily-standup and ceremony-cockpit when Kanban flow change is present. +- **EXTEND**: Documentation (agile-scrum-workflows) for Kanban flow and WIP/aging. + +## Capabilities + +- **kanban-flow**: `backlog flow` command; `.specfact/kanban.yaml` (WIP limits, columns, aging); flow metrics (WIP, aging, cycle time, throughput, blocked); Policy Engine integration for Kanban policies. + +## Impact + +- **Affected specs**: New `openspec/changes/backlog-06-kanban-flow-metrics/specs/kanban-flow/spec.md` (Given/When/Then for flow command, config, metrics, policy integration). +- **Affected code**: New command `specfact backlog flow`; kanban config loader; flow metrics aggregation; integration with Policy Engine for Kanban entry/exit. +- **Affected documentation** (): docs/guides/agile-scrum-workflows.md. +- **Integration points**: unify-policies-engine (#176), add-backlog-dependency-analysis-and-commands (#116) for backlog data. +- **Backward compatibility**: Additive; new command and config; existing Scrum commands unchanged. + +## Source Tracking + +- **GitHub Issue**: #183 +- **Issue URL**: +- **Repository**: nold-ai/specfact-cli +- **Last Synced Status**: proposed diff --git a/openspec/changes/backlog-06-kanban-flow-metrics/specs/kanban-flow/spec.md b/openspec/changes/backlog-06-kanban-flow-metrics/specs/kanban-flow/spec.md new file mode 100644 index 00000000..cbe0ce25 --- /dev/null +++ b/openspec/changes/backlog-06-kanban-flow-metrics/specs/kanban-flow/spec.md @@ -0,0 +1,78 @@ +# Kanban Flow Metrics (WIP, Aging, Flow) + +## ADDED Requirements + +### Requirement: backlog flow command + +The system SHALL provide `specfact backlog flow` (or `backlog flow-metrics`) that outputs Kanban flow view: WIP per column, aging WIP, cycle time/throughput when data exists, blocked time. + +**Rationale**: Δ4—Kanban-native workflow. + +#### Scenario: Run backlog flow + +**Given**: A project with backlog adapter and optional `.specfact/kanban.yaml` + +**When**: The user runs `specfact backlog flow` + +**Then**: The system outputs WIP per column, aging items, and (when available) cycle time/throughput and blocked time + +**And**: Output is available in JSON and Markdown + +**Acceptance Criteria**: + +- Command runs without error; output includes WIP and aging; cycle time/throughput when backlog supports it. +- When adapter does not provide state transitions (e.g. timestamps for column moves), the command runs in partial mode and output includes a clear disclaimer (e.g. "cycle time/throughput unavailable—partial mode"). + +### Requirement: Kanban config + +The system SHALL support `.specfact/kanban.yaml` for WIP limits, column definitions, and aging thresholds. Config SHALL integrate with Policy Engine (#176) for Kanban entry/exit policies per column. + +**Rationale**: Δ4—config-driven Kanban behavior. + +#### Scenario: Load kanban config + +**Given**: `.specfact/kanban.yaml` exists with columns and WIP limits + +**When**: The user runs `specfact backlog flow` or Policy Engine validates Kanban policies + +**Then**: The system loads kanban config and applies WIP/aging rules; missing config is handled gracefully + +**Acceptance Criteria**: + +- Config is optional; loader does not crash on missing/invalid config; Policy Engine can use columns for entry/exit. + +### Requirement: Flow metrics output + +The system SHALL produce flow metrics (WIP, aging, cycle time, throughput, blocked) in machine-readable (JSON) and human-readable (Markdown) formats. + +**Rationale**: Δ4—CI and tooling can consume flow data. + +#### Scenario: Export flow as JSON + +**Given**: `specfact backlog flow` has run + +**When**: The user requests JSON output (e.g. `--output json`) + +**Then**: The system outputs JSON with WIP per column, aging count, and optional cycle time/throughput/blocked + +**Acceptance Criteria**: + +- JSON schema includes WIP, aging, and optional flow metrics; Markdown summary is human-readable. + +### Requirement: Flow exceptions in backlog daily when Kanban mode + +The system SHALL allow `specfact backlog daily` to include an optional "flow exceptions" section (WIP/aging violations) when run with `--mode kanban` and flow data exists (e.g. when kanban-flow-metrics change is present). + +**Rationale**: Δ4 acceptance—backlog daily can include flow exceptions section when in Kanban mode. + +#### Scenario: Standup with flow exceptions in Kanban mode + +**Given**: User runs `specfact backlog daily --mode kanban` and flow data (WIP/aging) is available + +**When**: Flow exceptions section is enabled (default or flag) + +**Then**: Output MAY include a "flow exceptions" section with WIP limit violations and aging items when data exists + +**Acceptance Criteria**: + +- Flow exceptions section is optional; does not block daily when flow module or Kanban config is absent. diff --git a/openspec/changes/backlog-06-kanban-flow-metrics/tasks.md b/openspec/changes/backlog-06-kanban-flow-metrics/tasks.md new file mode 100644 index 00000000..10d45ee3 --- /dev/null +++ b/openspec/changes/backlog-06-kanban-flow-metrics/tasks.md @@ -0,0 +1,36 @@ +# Tasks: Kanban Flow Metrics (Δ4) + +## TDD / SDD order (enforced) + +Per `openspec/config.yaml`, **tests before code** apply. + +1. Spec deltas define behavior in `specs/kanban-flow/spec.md`. +2. **Tests second**: Write tests from spec scenarios; run tests and **expect failure**. +3. **Code last**: Implement until tests pass. + +--- + +## 1. Create git branch from dev + +- [ ] 1.1 Ensure on dev and up to date; create branch `feature/backlog-06-kanban-flow-metrics`; verify. + +## 2. Tests first (flow command, config, output) + +- [ ] 2.1 Write tests from spec: backlog flow command (WIP, aging, output format), kanban config load, JSON/Markdown output. +- [ ] 2.2 Run tests: `hatch run smart-test-unit`; **expect failure**. + +## 3. Implement Kanban Flow + +- [ ] 3.1 Implement `.specfact/kanban.yaml` loader (columns, WIP limits, aging thresholds). +- [ ] 3.2 Implement `specfact backlog flow` (WIP per column, aging, optional cycle time/throughput/blocked); JSON and Markdown output. +- [ ] 3.3 Integrate with Policy Engine (#176) for Kanban entry/exit policies when config present. +- [ ] 3.4 Run tests; **expect pass**. + +## 4. Quality gates and documentation + +- [ ] 4.1 Run format, type-check, contract-test. +- [ ] 4.2 Update docs (agile-scrum-workflows); CHANGELOG; version sync. + +## 5. Create Pull Request to dev + +- [ ] 5.1 Commit, push, create PR to dev; use repo PR template. diff --git a/openspec/changes/backlog-07-safe-pi-planning/proposal.md b/openspec/changes/backlog-07-safe-pi-planning/proposal.md new file mode 100644 index 00000000..43103cce --- /dev/null +++ b/openspec/changes/backlog-07-safe-pi-planning/proposal.md @@ -0,0 +1,33 @@ +# Change: SAFe PI Planning Essentials (WSJF + PI artifacts) — Δ5 + +## Why + +SAFe teams operate at PI/iteration/ART level. Today #116 (E4) includes ROAM list seed and #170 mentions SAFe usage, but there is no PI-level first-class support: no `backlog pi-summary`, no WSJF workflow, no PI readiness policy. Without `.specfact/safe.yaml` and PI artifacts, SAFe is an afterthought, not a supported framework. + +## What Changes + +- **NEW**: Add CLI command `specfact backlog pi-summary` for PI-level summary: PI scope, team commitments, cross-team dependency contracts, ROAM items (when available from #116). +- **NEW**: Config `.specfact/safe.yaml` for PI/iteration/ART settings; integrate with Policy Engine (#176) for PI readiness policy hooks. +- **NEW**: WSJF assistance: calculation with AI-assisted missing-field proposals and confirmation; output as JSON and Markdown. +- **EXTEND**: Policy Engine (#176) supports PI readiness policy when safe config is present. +- **EXTEND**: Dependency analysis (#116) cross-team dependency contracts and ROAM seed feed PI summary. +- **EXTEND**: Documentation (agile-scrum-workflows) for SAFe PI and WSJF. + +## Capabilities + +- **safe-pi-planning**: `backlog pi-summary` command; `.specfact/safe.yaml` (PI/iteration/ART); WSJF assistance (calculation + AI-assisted fields + confirmation); PI readiness in Policy Engine; cross-team dependency contracts. + +## Impact + +- **Affected specs**: New `openspec/changes/backlog-07-safe-pi-planning/specs/safe-pi/spec.md` (Given/When/Then for pi-summary, config, WSJF, policy integration). +- **Affected code**: New command `specfact backlog pi-summary`; safe config loader; WSJF calculation and AI-assisted field proposals; Policy Engine PI readiness hook. +- **Affected documentation** (): docs/guides/agile-scrum-workflows.md. +- **Integration points**: unify-policies-engine (#176), add-backlog-dependency-analysis-and-commands (#116) for ROAM and dependency contracts. +- **Backward compatibility**: Additive; new command and config; existing Scrum/Kanban commands unchanged. + +## Source Tracking + +- **GitHub Issue**: #184 +- **Issue URL**: +- **Repository**: nold-ai/specfact-cli +- **Last Synced Status**: proposed diff --git a/openspec/changes/backlog-07-safe-pi-planning/specs/safe-pi/spec.md b/openspec/changes/backlog-07-safe-pi-planning/specs/safe-pi/spec.md new file mode 100644 index 00000000..5ad61794 --- /dev/null +++ b/openspec/changes/backlog-07-safe-pi-planning/specs/safe-pi/spec.md @@ -0,0 +1,65 @@ +# SAFe PI Planning (PI summary, WSJF, PI readiness) + +## ADDED Requirements + +### Requirement: backlog pi-summary command + +The system SHALL provide `specfact backlog pi-summary` that outputs PI-level summary: PI scope, team commitments, cross-team dependency contracts, ROAM items (when available from dependency analysis). + +**Rationale**: Δ5—SAFe-first workflow. + +#### Scenario: Run pi-summary + +**Given**: A project with backlog adapter and optional `.specfact/safe.yaml` and dependency/ROAM data (#116) + +**When**: The user runs `specfact backlog pi-summary` + +**Then**: The system outputs PI scope, commitments, dependency contracts, and ROAM items when available + +**And**: Output is available in JSON and Markdown + +**And**: PI summary SHALL include a ROAM-ready Markdown table (e.g. risks/obstacles/assumptions/mitigations) when ROAM data is available + +**Acceptance Criteria**: + +- Command runs without error; output includes PI scope and (when data exists) commitments, dependency contracts, ROAM. +- PI summary includes a ROAM-ready Markdown table when ROAM data is available. + +### Requirement: SAFe config and PI readiness + +The system SHALL support `.specfact/safe.yaml` for PI/iteration/ART settings. Config SHALL integrate with Policy Engine (#176) for PI readiness policy hooks. + +**Rationale**: Δ5—config-driven SAFe behavior. + +#### Scenario: Load safe config + +**Given**: `.specfact/safe.yaml` exists with PI/iteration settings + +**When**: The user runs `specfact backlog pi-summary` or Policy Engine validates PI readiness + +**Then**: The system loads safe config and applies PI readiness rules; missing config is handled gracefully + +**Acceptance Criteria**: + +- Config is optional; Policy Engine can use PI readiness policy when config present. + +### Requirement: WSJF assistance + +The system SHALL provide WSJF calculation with AI-assisted missing-field proposals and user confirmation; output as JSON and Markdown. No automatic write without confirmation. + +**Rationale**: Δ5—WSJF for prioritization without silent writes. + +#### Scenario: WSJF with missing fields + +**Given**: User requests WSJF for a set of items with some missing WSJF fields + +**When**: The system runs WSJF assistance + +**Then**: The system proposes missing field values (e.g. job size, value) with confidence; user confirms before apply + +**And**: Output includes WSJF score and optional patch for fields + +**Acceptance Criteria**: + +- WSJF calculation is deterministic when fields present; AI-assisted proposals require confirmation; no silent writes. +- WSJF AI-assisted field proposals are applied only with explicit user confirmation or when user invokes with `--write` (per patch-mode / write gating); AI proposals never write fields without `--write`. diff --git a/openspec/changes/backlog-07-safe-pi-planning/tasks.md b/openspec/changes/backlog-07-safe-pi-planning/tasks.md new file mode 100644 index 00000000..dd0170d8 --- /dev/null +++ b/openspec/changes/backlog-07-safe-pi-planning/tasks.md @@ -0,0 +1,36 @@ +# Tasks: SAFe PI Planning (Δ5) + +## TDD / SDD order (enforced) + +Per `openspec/config.yaml`, **tests before code** apply. + +1. Spec deltas define behavior in `specs/safe-pi/spec.md`. +2. **Tests second**: Write tests from spec scenarios; run tests and **expect failure**. +3. **Code last**: Implement until tests pass. + +--- + +## 1. Create git branch from dev + +- [ ] 1.1 Ensure on dev and up to date; create branch `feature/backlog-07-safe-pi-planning`; verify. + +## 2. Tests first (pi-summary, config, WSJF) + +- [ ] 2.1 Write tests from spec: pi-summary command (scope, commitments, ROAM), safe config load, WSJF calculation and confirmation. +- [ ] 2.2 Run tests: `hatch run smart-test-unit`; **expect failure**. + +## 3. Implement SAFe PI + +- [ ] 3.1 Implement `.specfact/safe.yaml` loader (PI/iteration/ART); Policy Engine PI readiness hook. +- [ ] 3.2 Implement `specfact backlog pi-summary` (scope, commitments, dependency contracts, ROAM); JSON and Markdown output. +- [ ] 3.3 Implement WSJF assistance (calculation, AI-assisted missing fields, confirmation; no silent write). +- [ ] 3.4 Run tests; **expect pass**. + +## 4. Quality gates and documentation + +- [ ] 4.1 Run format, type-check, contract-test. +- [ ] 4.2 Update docs (agile-scrum-workflows); CHANGELOG; version sync. + +## 5. Create Pull Request to dev + +- [ ] 5.1 Commit, push, create PR to dev; use repo PR template. diff --git a/openspec/changes/backlog-08-risk-rollups/proposal.md b/openspec/changes/backlog-08-risk-rollups/proposal.md new file mode 100644 index 00000000..85a11b13 --- /dev/null +++ b/openspec/changes/backlog-08-risk-rollups/proposal.md @@ -0,0 +1,32 @@ +# Change: Explainable Risk Rollups (single score, traceable) — Δ6 + +## Why + +Every ceremony (standup, refinement, sprint summary, PI planning, release readiness) needs a consistent risk model with explainable inputs. Today risk is mentioned piecemeal in extensions but not modeled or wired. A single risk rollup mechanism—dependency criticality, policy failures, complexity flags, capacity overage, aging/WIP violations—makes all commands "exceptions-first" by default and gives teams one place to see "what might blow up." + +## What Changes + +- **NEW**: Introduce a Risk model with inputs: dependency criticality, policy failures (DoR/DoD/flow), complexity flags, capacity overage, aging/WIP violations. +- **NEW**: Produce a single rollup score (low/medium/high) with traceable contributions: JSON output with input contributions, reasons, and evidence pointers. +- **NEW**: Integrate risk rollup into standup, refinement, sprint-summary, (when available) PI summary, and (when available) `backlog verify-readiness` (release) so each command can surface risk section. +- **EXTEND**: Policy Engine (#176) and dependency analysis (#116) feed risk inputs; sprint-planning (#170) and complexity/splitting (#171) contribute capacity and complexity signals. +- **EXTEND**: Documentation (agile-scrum-workflows) for risk model and rollup usage. + +## Capabilities + +- **risk-rollups**: Risk model with configurable inputs; single rollup score (low/medium/high); JSON output with input contributions, reasons, evidence pointers, optional weights; integration with standup, refinement, sprint-summary, verify-readiness (when available). + +## Impact + +- **Affected specs**: New `openspec/changes/backlog-08-risk-rollups/specs/risk-rollups/spec.md` (Given/When/Then for risk model, rollup, JSON output, command integration). +- **Affected code**: New module for risk model (e.g. `src/specfact_cli/risk/` or under commands); rollup aggregation; CLI output for risk in backlog daily, refine, sprint-summary. +- **Affected documentation** (): docs/guides/agile-scrum-workflows.md. +- **Integration points**: add-backlog-dependency-analysis-and-commands (#116), unify-policies-engine (#176), sprint-planning-capacity-commitment-support (#170), story-complexity-splitting-hints-support (#171). +- **Backward compatibility**: Additive; existing commands unchanged until risk section is enabled or requested. + +## Source Tracking + +- **GitHub Issue**: #182 +- **Issue URL**: +- **Repository**: nold-ai/specfact-cli +- **Last Synced Status**: proposed diff --git a/openspec/changes/backlog-08-risk-rollups/specs/risk-rollups/spec.md b/openspec/changes/backlog-08-risk-rollups/specs/risk-rollups/spec.md new file mode 100644 index 00000000..b63c8f07 --- /dev/null +++ b/openspec/changes/backlog-08-risk-rollups/specs/risk-rollups/spec.md @@ -0,0 +1,77 @@ +# Risk Rollups (Explainable, Traceable) + +## ADDED Requirements + +### Requirement: Risk model with configurable inputs + +The system SHALL provide a Risk model that aggregates inputs: dependency criticality, policy failures (DoR/DoD/flow), complexity flags, capacity overage, aging/WIP violations. Inputs SHALL be configurable so teams can enable/disable sources. + +**Rationale**: Δ6—single substrate for "what might blow up" across ceremonies. + +#### Scenario: Compute risk rollup + +**Given**: A project with dependency graph and policy results (and optional capacity/complexity data) + +**When**: The system computes risk rollup + +**Then**: The system aggregates enabled inputs and produces a single score (low/medium/high) + +**And**: Output includes traceable contributions: each input with reason and evidence pointer + +**Acceptance Criteria**: + +- Rollup score is low/medium/high; JSON output includes `contributions` array with source, reason, evidence pointer, and optional weight (contribution weight for explainability). + +### Requirement: Risk rollup JSON output + +The system SHALL produce machine-readable risk output: JSON with rollup score, contributions (source, reason, evidence pointer), and optional human-readable summary. + +**Rationale**: Δ6—CI gates and tooling can consume risk without parsing prose. + +#### Scenario: Export risk as JSON + +**Given**: Risk rollup has been computed + +**When**: The user requests JSON output (e.g. `--output json` or risk subcommand) + +**Then**: The system outputs JSON with score, contributions array, and optional summary field + +**Acceptance Criteria**: + +- JSON schema includes score (enum: low/medium/high), contributions (array of { source, reason, evidence, optional weight }). + +### Requirement: Risk integration in backlog commands + +The system SHALL allow standup, refinement, and sprint-summary commands to include an optional risk section (rollup + top contributions) when risk data is available. + +**Rationale**: Δ6—every ceremony can be exceptions-first. + +#### Scenario: Standup shows risk section + +**Given**: `specfact backlog daily` is run and dependency/policy (and optional capacity) data exists + +**When**: Risk rollup is enabled (default or flag) + +**Then**: Output includes a risk section with rollup score and top contributions (or "No significant risk" when low) + +**Acceptance Criteria**: + +- Risk section is present when enabled; does not block command when risk module or dependencies are unavailable. + +### Requirement: Risk integration in verify-readiness (release) + +When `backlog verify-readiness` (or equivalent release-readiness command) exists, the system SHALL allow it to include an optional risk section (rollup + top contributions) so release view includes risk. + +**Rationale**: Δ6—risk used in verify-readiness (release) per 2026-02-01. + +#### Scenario: Verify-readiness shows risk section + +**Given**: `specfact backlog verify-readiness` (or equivalent) is run and risk data is available + +**When**: Risk rollup is enabled (default or flag) + +**Then**: Output MAY include a risk section with rollup score and top contributions when the command is implemented + +**Acceptance Criteria**: + +- When verify-readiness command exists, risk section is integrable; does not block when risk module is absent. diff --git a/openspec/changes/backlog-08-risk-rollups/tasks.md b/openspec/changes/backlog-08-risk-rollups/tasks.md new file mode 100644 index 00000000..3c696176 --- /dev/null +++ b/openspec/changes/backlog-08-risk-rollups/tasks.md @@ -0,0 +1,36 @@ +# Tasks: Explainable Risk Rollups (Δ6) + +## TDD / SDD order (enforced) + +Per `openspec/config.yaml`, **tests before code** apply. + +1. Spec deltas define behavior in `specs/risk-rollups/spec.md`. +2. **Tests second**: Write tests from spec scenarios; run tests and **expect failure**. +3. **Code last**: Implement until tests pass. + +--- + +## 1. Create git branch from dev + +- [ ] 1.1 Ensure on dev and up to date; create branch `feature/backlog-08-risk-rollups`; verify. + +## 2. Tests first (risk model, rollup, JSON output) + +- [ ] 2.1 Write tests from spec: risk model inputs aggregation, rollup score (low/medium/high), JSON output shape (score, contributions). +- [ ] 2.2 Run tests: `hatch run smart-test-unit`; **expect failure**. + +## 3. Implement Risk Rollups + +- [ ] 3.1 Implement risk model (configurable inputs: dependency criticality, policy failures, complexity, capacity, aging/WIP). +- [ ] 3.2 Implement rollup aggregation and JSON output (score, contributions with source, reason, evidence). +- [ ] 3.3 Integrate risk section into backlog daily (and optionally refine, sprint-summary) when data available. +- [ ] 3.4 Run tests; **expect pass**. + +## 4. Quality gates and documentation + +- [ ] 4.1 Run format, type-check, contract-test. +- [ ] 4.2 Update docs (agile-scrum-workflows); CHANGELOG; version sync. + +## 5. Create Pull Request to dev + +- [ ] 5.1 Commit, push, create PR to dev; use repo PR template. diff --git a/openspec/changes/definition-of-done-support/CHANGE_VALIDATION.md b/openspec/changes/backlog-09-definition-of-done-support/CHANGE_VALIDATION.md similarity index 97% rename from openspec/changes/definition-of-done-support/CHANGE_VALIDATION.md rename to openspec/changes/backlog-09-definition-of-done-support/CHANGE_VALIDATION.md index 5e9b6d6f..e5677a10 100644 --- a/openspec/changes/definition-of-done-support/CHANGE_VALIDATION.md +++ b/openspec/changes/backlog-09-definition-of-done-support/CHANGE_VALIDATION.md @@ -71,4 +71,4 @@ None. Change is additive: new DoD config schema, loader, validator; optional DoD ## Validation Artifacts - No temporary workspace used (dry-run analysis only). -- Change directory: `openspec/changes/definition-of-done-support/` +- Change directory: `openspec/changes/backlog-09-definition-of-done-support/` diff --git a/openspec/changes/definition-of-done-support/design.md b/openspec/changes/backlog-09-definition-of-done-support/design.md similarity index 100% rename from openspec/changes/definition-of-done-support/design.md rename to openspec/changes/backlog-09-definition-of-done-support/design.md diff --git a/openspec/changes/definition-of-done-support/proposal.md b/openspec/changes/backlog-09-definition-of-done-support/proposal.md similarity index 92% rename from openspec/changes/definition-of-done-support/proposal.md rename to openspec/changes/backlog-09-definition-of-done-support/proposal.md index 0176c996..1f5ed9cb 100644 --- a/openspec/changes/definition-of-done-support/proposal.md +++ b/openspec/changes/backlog-09-definition-of-done-support/proposal.md @@ -17,7 +17,7 @@ SpecFact CLI has Definition of Ready (DoR) for backlog refinement (readiness for ## Impact -- **Affected specs**: New `openspec/changes/definition-of-done-support/specs/definition-of-done/spec.md` (Given/When/Then for DoD config, validation, status output). +- **Affected specs**: New `openspec/changes/backlog-09-definition-of-done-support/specs/definition-of-done/spec.md` (Given/When/Then for DoD config, validation, status output). - **Affected code**: `src/specfact_cli/` (DoD config and validator); `src/specfact_cli/commands/backlog_commands.py` (optional DoD check for done items under backlog group). - **Affected documentation** (): docs/guides/agile-scrum-workflows.md, docs/guides/backlog-refinement.md for DoD. - **Integration points**: Existing backlog list/refine/export; BacklogItem state=Done; DoR patterns for reuse. diff --git a/openspec/changes/definition-of-done-support/specs/definition-of-done/spec.md b/openspec/changes/backlog-09-definition-of-done-support/specs/definition-of-done/spec.md similarity index 100% rename from openspec/changes/definition-of-done-support/specs/definition-of-done/spec.md rename to openspec/changes/backlog-09-definition-of-done-support/specs/definition-of-done/spec.md diff --git a/openspec/changes/definition-of-done-support/tasks.md b/openspec/changes/backlog-09-definition-of-done-support/tasks.md similarity index 88% rename from openspec/changes/definition-of-done-support/tasks.md rename to openspec/changes/backlog-09-definition-of-done-support/tasks.md index d0903043..0d70a41a 100644 --- a/openspec/changes/definition-of-done-support/tasks.md +++ b/openspec/changes/backlog-09-definition-of-done-support/tasks.md @@ -4,7 +4,7 @@ Per `openspec/config.yaml`, **tests before code** apply to any task that adds or changes behavior. -1. **Spec deltas** define behavior (Given/When/Then) in `openspec/changes/definition-of-done-support/specs/definition-of-done/spec.md`. +1. **Spec deltas** define behavior (Given/When/Then) in `openspec/changes/backlog-09-definition-of-done-support/specs/definition-of-done/spec.md`. 2. **Tests second**: Write unit/integration tests from those scenarios; run tests and **expect failure** (no implementation yet). 3. **Code last**: Implement until tests pass and behavior satisfies the spec. @@ -15,8 +15,8 @@ Do not implement production code for new behavior until the corresponding tests ## 1. Create git branch from dev - [ ] 1.1 Ensure we're on dev and up to date: `git checkout dev && git pull origin dev` -- [ ] 1.2 Create branch with Development link to issue (if exists): `gh issue develop --repo nold-ai/specfact-cli --name feature/definition-of-done-support --checkout` -- [ ] 1.3 Or create branch without issue link: `git checkout -b feature/definition-of-done-support` (if no issue yet) +- [ ] 1.2 Create branch with Development link to issue (if exists): `gh issue develop --repo nold-ai/specfact-cli --name feature/backlog-09-definition-of-done-support --checkout` +- [ ] 1.3 Or create branch without issue link: `git checkout -b feature/backlog-09-definition-of-done-support` (if no issue yet) - [ ] 1.4 Verify branch was created: `git branch --show-current` ## 2. Create GitHub issue in nold-ai/specfact-cli (mandatory) @@ -68,6 +68,6 @@ Do not implement production code for new behavior until the corresponding tests ## 9. Create Pull Request to dev - [ ] 9.1 Ensure all changes are committed: `git add .` and `git commit -m "feat(backlog): add Definition of Done (DoD) support for done items"` -- [ ] 9.2 Push to remote: `git push origin feature/definition-of-done-support` -- [ ] 9.3 Create PR: `gh pr create --repo nold-ai/specfact-cli --base dev --head feature/definition-of-done-support --title "feat(backlog): add Definition of Done (DoD) support for done items" --body-file ` (use repo PR template; add OpenSpec change ID `definition-of-done-support` and summary; reference GitHub issue with `Fixes nold-ai/specfact-cli#`). +- [ ] 9.2 Push to remote: `git push origin feature/backlog-09-definition-of-done-support` +- [ ] 9.3 Create PR: `gh pr create --repo nold-ai/specfact-cli --base dev --head feature/backlog-09-definition-of-done-support --title "feat(backlog): add Definition of Done (DoD) support for done items" --body-file ` (use repo PR template; add OpenSpec change ID `backlog-09-definition-of-done-support` and summary; reference GitHub issue with `Fixes nold-ai/specfact-cli#`). - [ ] 9.4 Verify PR and branch are linked to issue in Development section. diff --git a/openspec/changes/add-bundle-mapping-strategy/CHANGE_VALIDATION.md b/openspec/changes/bundle-01-add-bundle-mapping-strategy/CHANGE_VALIDATION.md similarity index 97% rename from openspec/changes/add-bundle-mapping-strategy/CHANGE_VALIDATION.md rename to openspec/changes/bundle-01-add-bundle-mapping-strategy/CHANGE_VALIDATION.md index e1df2893..54fac81f 100644 --- a/openspec/changes/add-bundle-mapping-strategy/CHANGE_VALIDATION.md +++ b/openspec/changes/bundle-01-add-bundle-mapping-strategy/CHANGE_VALIDATION.md @@ -77,7 +77,7 @@ This change does not modify existing interfaces or contracts. ## Validation Artifacts -- Change directory: `openspec/changes/add-bundle-mapping-strategy/` +- Change directory: `openspec/changes/bundle-01-add-bundle-mapping-strategy/` - Spec files: - `specs/bundle-mapping/spec.md` - Bundle mapping requirements - `specs/confidence-scoring/spec.md` - Confidence scoring requirements diff --git a/openspec/changes/add-bundle-mapping-strategy/proposal.md b/openspec/changes/bundle-01-add-bundle-mapping-strategy/proposal.md similarity index 100% rename from openspec/changes/add-bundle-mapping-strategy/proposal.md rename to openspec/changes/bundle-01-add-bundle-mapping-strategy/proposal.md diff --git a/openspec/changes/add-bundle-mapping-strategy/specs/bundle-mapping/spec.md b/openspec/changes/bundle-01-add-bundle-mapping-strategy/specs/bundle-mapping/spec.md similarity index 100% rename from openspec/changes/add-bundle-mapping-strategy/specs/bundle-mapping/spec.md rename to openspec/changes/bundle-01-add-bundle-mapping-strategy/specs/bundle-mapping/spec.md diff --git a/openspec/changes/add-bundle-mapping-strategy/specs/confidence-scoring/spec.md b/openspec/changes/bundle-01-add-bundle-mapping-strategy/specs/confidence-scoring/spec.md similarity index 100% rename from openspec/changes/add-bundle-mapping-strategy/specs/confidence-scoring/spec.md rename to openspec/changes/bundle-01-add-bundle-mapping-strategy/specs/confidence-scoring/spec.md diff --git a/openspec/changes/add-bundle-mapping-strategy/tasks.md b/openspec/changes/bundle-01-add-bundle-mapping-strategy/tasks.md similarity index 100% rename from openspec/changes/add-bundle-mapping-strategy/tasks.md rename to openspec/changes/bundle-01-add-bundle-mapping-strategy/tasks.md diff --git a/openspec/changes/ceremony-01-ceremony-cockpit/proposal.md b/openspec/changes/ceremony-01-ceremony-cockpit/proposal.md new file mode 100644 index 00000000..73dd47db --- /dev/null +++ b/openspec/changes/ceremony-01-ceremony-cockpit/proposal.md @@ -0,0 +1,32 @@ +# Change: Ceremony Cockpit (UX layer for findability) — Δ3 + +## Why + +Teams think in ceremonies ("standup," "refinement," "planning"). Without ceremony entry points, adoption friction remains high—users must remember `backlog daily`, `backlog refine`, `backlog sprint-summary` instead of `ceremony standup`, `ceremony refinement`, `ceremony planning`. Ceremony aliases plus mode switch (scrum|kanban|safe) and exceptions-first defaults are a pure UX/ergonomics win with minimal implementation cost. + +## What Changes + +- **NEW**: Add ceremony-oriented entry points: `specfact ceremony standup` → `backlog daily`, `specfact ceremony refinement` → `backlog refine`, `specfact ceremony planning` → `backlog sprint-summary` (and optional `ceremony flow`, `ceremony pi-summary` when those changes exist). +- **NEW**: Each ceremony command SHALL emit human view (Markdown/table), machine view (JSON when underlying backlog command supports `--output json`), and optional copilot prompt export; ceremony layer inherits or forwards these output formats from the underlying backlog command. +- **NEW**: Add `--mode scrum|kanban|safe` at ceremony level so defaults for filters and sections follow framework. +- **EXTEND**: Exceptions-first default section order (blockers, policy failures, aging, normal) when applicable; integrate with daily-standup-exceptions-first (E1) and Policy Engine (#176). +- **EXTEND**: Documentation (agile-scrum-workflows) for ceremony commands and mode switch. + +## Capabilities + +- **ceremony-cockpit**: Ceremony aliases (standup, refinement, planning, optional flow/pi-summary); mode switch (scrum|kanban|safe); exceptions-first defaults; Policy Engine integration for section ordering. + +## Impact + +- **Affected specs**: New `openspec/changes/ceremony-01-ceremony-cockpit/specs/ceremony-cockpit/spec.md` (Given/When/Then for ceremony aliases, mode, output order). +- **Affected code**: New command group `specfact ceremony` with subcommands delegating to backlog; `--mode` and default section order wiring. +- **Affected documentation** (): docs/guides/agile-scrum-workflows.md. +- **Integration points**: daily-standup-exceptions-first (E1), sprint-planning-capacity-commitment-support (#170), unify-policies-engine (#176); optional kanban-flow-metrics (Δ4), safe-pi-planning (Δ5). +- **Backward compatibility**: Additive; existing `backlog daily`, `backlog refine`, `backlog sprint-summary` unchanged; ceremony is an alias layer. + +## Source Tracking + +- **GitHub Issue**: #185 +- **Issue URL**: +- **Repository**: nold-ai/specfact-cli +- **Last Synced Status**: proposed diff --git a/openspec/changes/ceremony-01-ceremony-cockpit/specs/ceremony-cockpit/spec.md b/openspec/changes/ceremony-01-ceremony-cockpit/specs/ceremony-cockpit/spec.md new file mode 100644 index 00000000..702b96d1 --- /dev/null +++ b/openspec/changes/ceremony-01-ceremony-cockpit/specs/ceremony-cockpit/spec.md @@ -0,0 +1,58 @@ +# Ceremony Cockpit (Aliases, Mode, Exceptions-First) + +## ADDED Requirements + +### Requirement: Ceremony aliases + +The system SHALL provide ceremony-oriented entry points: `specfact ceremony standup` (delegates to `backlog daily`), `specfact ceremony refinement` (delegates to `backlog refine`), `specfact ceremony planning` (delegates to `backlog sprint-summary`). Optional: `ceremony flow` → `backlog flow`, `ceremony pi-summary` → `backlog pi-summary` when those commands exist. + +**Rationale**: Δ3—findability by ceremony. + +#### Scenario: Run ceremony standup + +**Given**: SpecFact CLI is installed + +**When**: The user runs `specfact ceremony standup` + +**Then**: The system executes the same behavior as `specfact backlog daily` (with same options and defaults) + +**Acceptance Criteria**: + +- `ceremony standup` and `backlog daily` produce equivalent output for same inputs; same for refinement and planning. +- Ceremony commands inherit output formats from underlying backlog commands: human view (Markdown/table), machine view (JSON when backlog command supports `--output json`), optional copilot prompt export when supported. + +### Requirement: Mode switch at ceremony level + +The system SHALL support `--mode scrum|kanban|safe` at ceremony level so defaults for filters and sections follow the selected framework (e.g. Kanban: flow-oriented sections; SAFe: PI-oriented hints when available). + +**Rationale**: Δ3—one flag for framework context. + +#### Scenario: Ceremony with mode + +**Given**: User runs `specfact ceremony standup --mode kanban` + +**When**: The command executes + +**Then**: Defaults for filters and sections follow Kanban (e.g. flow/WIP context when available); output order may follow exceptions-first when data exists + +**Acceptance Criteria**: + +- Mode is passed through to underlying backlog command; behavior aligns with mode when backend supports it. + +### Requirement: Exceptions-first default order + +The system SHALL apply exceptions-first default section order (blockers, policy failures, aging, normal) for ceremony standup when Policy Engine (#176) or flow data exists; configurable or overridable. + +**Rationale**: Δ3—exceptions-first by default for ceremonies. + +#### Scenario: Standup with exceptions-first + +**Given**: User runs `specfact ceremony standup` (or `backlog daily`) and policy/flow data exists + +**When**: No override disables exceptions-first + +**Then**: Output sections are ordered: (1) blockers and dependency-critical, (2) policy failures, (3) aging/stalled, (4) normal status + +**Acceptance Criteria**: + +- Order is default when data available; existing backlog daily behavior is extended, not replaced; backward compatible. diff --git a/openspec/changes/ceremony-01-ceremony-cockpit/tasks.md b/openspec/changes/ceremony-01-ceremony-cockpit/tasks.md new file mode 100644 index 00000000..371f005e --- /dev/null +++ b/openspec/changes/ceremony-01-ceremony-cockpit/tasks.md @@ -0,0 +1,36 @@ +# Tasks: Ceremony Cockpit (Δ3) + +## TDD / SDD order (enforced) + +Per `openspec/config.yaml`, **tests before code** apply. + +1. Spec deltas define behavior in `specs/ceremony-cockpit/spec.md`. +2. **Tests second**: Write tests from spec scenarios; run tests and **expect failure**. +3. **Code last**: Implement until tests pass. + +--- + +## 1. Create git branch from dev + +- [ ] 1.1 Ensure on dev and up to date; create branch `feature/ceremony-01-ceremony-cockpit`; verify. + +## 2. Tests first (ceremony aliases, mode, order) + +- [ ] 2.1 Write tests from spec: ceremony standup/refinement/planning delegate to backlog; --mode passed through; exceptions-first order when data exists. +- [ ] 2.2 Run tests: `hatch run smart-test-unit`; **expect failure**. + +## 3. Implement Ceremony Cockpit + +- [ ] 3.1 Add command group `specfact ceremony` with subcommands standup, refinement, planning (delegate to backlog daily, refine, sprint-summary). +- [ ] 3.2 Add `--mode scrum|kanban|safe` at ceremony level; pass through to backlog commands. +- [ ] 3.3 Wire exceptions-first default section order for standup when Policy Engine or flow data available. +- [ ] 3.4 Run tests; **expect pass**. + +## 4. Quality gates and documentation + +- [ ] 4.1 Run format, type-check, contract-test. +- [ ] 4.2 Update docs (agile-scrum-workflows); CHANGELOG; version sync. + +## 5. Create Pull Request to dev + +- [ ] 5.1 Commit, push, create PR to dev; use repo PR template. diff --git a/openspec/changes/patch-mode-preview-apply/CHANGE_VALIDATION.md b/openspec/changes/patch-01-patch-mode-preview-apply/CHANGE_VALIDATION.md similarity index 100% rename from openspec/changes/patch-mode-preview-apply/CHANGE_VALIDATION.md rename to openspec/changes/patch-01-patch-mode-preview-apply/CHANGE_VALIDATION.md diff --git a/openspec/changes/patch-mode-preview-apply/proposal.md b/openspec/changes/patch-01-patch-mode-preview-apply/proposal.md similarity index 93% rename from openspec/changes/patch-mode-preview-apply/proposal.md rename to openspec/changes/patch-01-patch-mode-preview-apply/proposal.md index 257fcd7f..b3adbb33 100644 --- a/openspec/changes/patch-mode-preview-apply/proposal.md +++ b/openspec/changes/patch-01-patch-mode-preview-apply/proposal.md @@ -18,7 +18,7 @@ Reporting findings is not enough; teams love tools that propose fixes they can s ## Impact -- **Affected specs**: New `openspec/changes/patch-mode-preview-apply/specs/patch-mode/spec.md` (Given/When/Then for patch generation, apply local, write upstream). +- **Affected specs**: New `openspec/changes/patch-01-patch-mode-preview-apply/specs/patch-mode/spec.md` (Given/When/Then for patch generation, apply local, write upstream). - **Affected code**: New module or commands for patch pipeline (e.g. `src/specfact_cli/commands/patch_commands.py` or under backlog); `specfact patch apply`; integration with backlog refine, Policy Engine (suggest → patch). - **Affected documentation** (): docs/guides/agile-scrum-workflows.md, docs/guides/devops-adapter-integration.md. - **Integration points**: unify-policies-engine (suggest → patch), daily-standup-exceptions-first (standup notes patch), story-complexity-splitting-hints-support (split proposal patch). diff --git a/openspec/changes/patch-mode-preview-apply/specs/patch-mode/spec.md b/openspec/changes/patch-01-patch-mode-preview-apply/specs/patch-mode/spec.md similarity index 100% rename from openspec/changes/patch-mode-preview-apply/specs/patch-mode/spec.md rename to openspec/changes/patch-01-patch-mode-preview-apply/specs/patch-mode/spec.md diff --git a/openspec/changes/patch-mode-preview-apply/tasks.md b/openspec/changes/patch-01-patch-mode-preview-apply/tasks.md similarity index 97% rename from openspec/changes/patch-mode-preview-apply/tasks.md rename to openspec/changes/patch-01-patch-mode-preview-apply/tasks.md index 89abc622..f33ebc28 100644 --- a/openspec/changes/patch-mode-preview-apply/tasks.md +++ b/openspec/changes/patch-01-patch-mode-preview-apply/tasks.md @@ -12,7 +12,7 @@ Per `openspec/config.yaml`, **tests before code** apply. ## 1. Create git branch from dev -- [ ] 1.1 Ensure on dev and up to date; create branch `feature/patch-mode-preview-apply`; verify. +- [ ] 1.1 Ensure on dev and up to date; create branch `feature/patch-01-patch-mode-preview-apply`; verify. ## 2. Tests first (patch generate, apply local, write upstream) diff --git a/openspec/changes/unify-policies-engine/CHANGE_VALIDATION.md b/openspec/changes/policy-01-unify-policies-engine/CHANGE_VALIDATION.md similarity index 100% rename from openspec/changes/unify-policies-engine/CHANGE_VALIDATION.md rename to openspec/changes/policy-01-unify-policies-engine/CHANGE_VALIDATION.md diff --git a/openspec/changes/unify-policies-engine/proposal.md b/openspec/changes/policy-01-unify-policies-engine/proposal.md similarity index 93% rename from openspec/changes/unify-policies-engine/proposal.md rename to openspec/changes/policy-01-unify-policies-engine/proposal.md index e845d7b3..94902de4 100644 --- a/openspec/changes/unify-policies-engine/proposal.md +++ b/openspec/changes/policy-01-unify-policies-engine/proposal.md @@ -21,7 +21,7 @@ Teams love tools that enforce working agreements consistently. Today DoR/DoD are ## Impact -- **Affected specs**: New `openspec/changes/unify-policies-engine/specs/policy-engine/spec.md` (Given/When/Then for validate, suggest, policies, output formats). +- **Affected specs**: New `openspec/changes/policy-01-unify-policies-engine/specs/policy-engine/spec.md` (Given/When/Then for validate, suggest, policies, output formats). - **Affected code**: New module for policy engine (e.g. `src/specfact_cli/policy/` or under commands); CLI `specfact policy validate`, `specfact policy suggest`; integration points for refinement, standup, sprint-summary (DoR coverage). - **Affected documentation** (): docs/guides/agile-scrum-workflows.md, docs/guides/devops-adapter-integration.md. - **Integration points**: definition-of-done-support, daily-standup-exceptions-first, sprint-planning-capacity-commitment-support (DoR coverage), patch-mode-preview-apply (suggest → patch). diff --git a/openspec/changes/unify-policies-engine/specs/policy-engine/spec.md b/openspec/changes/policy-01-unify-policies-engine/specs/policy-engine/spec.md similarity index 100% rename from openspec/changes/unify-policies-engine/specs/policy-engine/spec.md rename to openspec/changes/policy-01-unify-policies-engine/specs/policy-engine/spec.md diff --git a/openspec/changes/unify-policies-engine/tasks.md b/openspec/changes/policy-01-unify-policies-engine/tasks.md similarity index 92% rename from openspec/changes/unify-policies-engine/tasks.md rename to openspec/changes/policy-01-unify-policies-engine/tasks.md index c79271f6..fbb9e151 100644 --- a/openspec/changes/unify-policies-engine/tasks.md +++ b/openspec/changes/policy-01-unify-policies-engine/tasks.md @@ -12,7 +12,7 @@ Per `openspec/config.yaml`, **tests before code** apply. ## 1. Create git branch from dev -- [ ] 1.1 Ensure on dev and up to date; create branch `feature/unify-policies-engine`; verify. +- [ ] 1.1 Ensure on dev and up to date; create branch `feature/policy-01-unify-policies-engine`; verify. ## 2. Tests first (policy validate, suggest, config) diff --git a/openspec/changes/add-sidecar-flask-support/CHANGE_VALIDATION.md b/openspec/changes/sidecar-01-add-sidecar-flask-support/CHANGE_VALIDATION.md similarity index 100% rename from openspec/changes/add-sidecar-flask-support/CHANGE_VALIDATION.md rename to openspec/changes/sidecar-01-add-sidecar-flask-support/CHANGE_VALIDATION.md diff --git a/openspec/changes/add-sidecar-flask-support/CONTRACT-STRENGTHENING.md b/openspec/changes/sidecar-01-add-sidecar-flask-support/CONTRACT-STRENGTHENING.md similarity index 100% rename from openspec/changes/add-sidecar-flask-support/CONTRACT-STRENGTHENING.md rename to openspec/changes/sidecar-01-add-sidecar-flask-support/CONTRACT-STRENGTHENING.md diff --git a/openspec/changes/add-sidecar-flask-support/CROSSHAIR-EXECUTION.md b/openspec/changes/sidecar-01-add-sidecar-flask-support/CROSSHAIR-EXECUTION.md similarity index 100% rename from openspec/changes/add-sidecar-flask-support/CROSSHAIR-EXECUTION.md rename to openspec/changes/sidecar-01-add-sidecar-flask-support/CROSSHAIR-EXECUTION.md diff --git a/openspec/changes/add-sidecar-flask-support/DEPENDENCY-INSTALLATION.md b/openspec/changes/sidecar-01-add-sidecar-flask-support/DEPENDENCY-INSTALLATION.md similarity index 100% rename from openspec/changes/add-sidecar-flask-support/DEPENDENCY-INSTALLATION.md rename to openspec/changes/sidecar-01-add-sidecar-flask-support/DEPENDENCY-INSTALLATION.md diff --git a/openspec/changes/add-sidecar-flask-support/FLASK-SIDECAR-USAGE.md b/openspec/changes/sidecar-01-add-sidecar-flask-support/FLASK-SIDECAR-USAGE.md similarity index 100% rename from openspec/changes/add-sidecar-flask-support/FLASK-SIDECAR-USAGE.md rename to openspec/changes/sidecar-01-add-sidecar-flask-support/FLASK-SIDECAR-USAGE.md diff --git a/openspec/changes/add-sidecar-flask-support/IMPLEMENTATION_STATUS.md b/openspec/changes/sidecar-01-add-sidecar-flask-support/IMPLEMENTATION_STATUS.md similarity index 100% rename from openspec/changes/add-sidecar-flask-support/IMPLEMENTATION_STATUS.md rename to openspec/changes/sidecar-01-add-sidecar-flask-support/IMPLEMENTATION_STATUS.md diff --git a/openspec/changes/add-sidecar-flask-support/INVESTIGATION.md b/openspec/changes/sidecar-01-add-sidecar-flask-support/INVESTIGATION.md similarity index 100% rename from openspec/changes/add-sidecar-flask-support/INVESTIGATION.md rename to openspec/changes/sidecar-01-add-sidecar-flask-support/INVESTIGATION.md diff --git a/openspec/changes/add-sidecar-flask-support/proposal.md b/openspec/changes/sidecar-01-add-sidecar-flask-support/proposal.md similarity index 100% rename from openspec/changes/add-sidecar-flask-support/proposal.md rename to openspec/changes/sidecar-01-add-sidecar-flask-support/proposal.md diff --git a/openspec/changes/add-sidecar-flask-support/specs/sidecar-validation/spec.md b/openspec/changes/sidecar-01-add-sidecar-flask-support/specs/sidecar-validation/spec.md similarity index 100% rename from openspec/changes/add-sidecar-flask-support/specs/sidecar-validation/spec.md rename to openspec/changes/sidecar-01-add-sidecar-flask-support/specs/sidecar-validation/spec.md diff --git a/openspec/changes/add-sidecar-flask-support/tasks.md b/openspec/changes/sidecar-01-add-sidecar-flask-support/tasks.md similarity index 97% rename from openspec/changes/add-sidecar-flask-support/tasks.md rename to openspec/changes/sidecar-01-add-sidecar-flask-support/tasks.md index c0d17821..11d85f83 100644 --- a/openspec/changes/add-sidecar-flask-support/tasks.md +++ b/openspec/changes/sidecar-01-add-sidecar-flask-support/tasks.md @@ -2,9 +2,9 @@ ## 1. Git Workflow Setup -- [x] 1.1 Create git branch `feature/add-sidecar-flask-support` from `dev` branch +- [x] 1.1 Create git branch `feature/sidecar-01-add-sidecar-flask-support` from `dev` branch - [x] 1.1.1 Ensure we're on dev and up to date: `git checkout dev && git pull origin dev` - - [x] 1.1.2 Create branch: `git checkout -b feature/add-sidecar-flask-support` + - [x] 1.1.2 Create branch: `git checkout -b feature/sidecar-01-add-sidecar-flask-support` - [x] 1.1.3 Verify branch was created: `git branch --show-current` ## 2. Add Flask Framework Type @@ -268,7 +268,7 @@ - [x] 12.1 Prepare changes for commit - [x] 12.1.1 Ensure all changes are committed: `git add .` - [x] 12.1.2 Commit with conventional message: `git commit -m "feat: add Flask framework support to sidecar validation"` - - [x] 12.1.3 Push to remote: `git push origin feature/add-sidecar-flask-support` + - [x] 12.1.3 Push to remote: `git push origin feature/sidecar-01-add-sidecar-flask-support` - [x] 12.2 Create PR body from template - [x] 12.2.1 Create PR body file: `PR_BODY_FILE="/tmp/pr-body-add-sidecar-flask-support.md"` @@ -278,7 +278,7 @@ - [x] 12.2.3 Verify PR body file was created: `cat "$PR_BODY_FILE"` (contains issue reference `nold-ai/specfact-cli#102`) - [x] 12.3 Create Pull Request using gh CLI - - [x] 12.3.1 Create PR: `gh pr create --repo nold-ai/specfact-cli --base dev --head feature/add-sidecar-flask-support --title "feat: add Flask framework support to sidecar validation" --body-file "$PR_BODY_FILE"` + - [x] 12.3.1 Create PR: `gh pr create --repo nold-ai/specfact-cli --base dev --head feature/sidecar-01-add-sidecar-flask-support --title "feat: add Flask framework support to sidecar validation" --body-file "$PR_BODY_FILE"` - [x] 12.3.2 Verify PR was created and capture PR number: __PR #103__ created at - [x] 12.3.3 Link PR to project: `gh project item-add 1 --owner nold-ai --url "https://github.com/nold-ai/specfact-cli/pull/103"` (attempted - may require manual setup) - [x] 12.3.4 Verify Development link: PR body contains `Fixes nold-ai/specfact-cli#102`, which should automatically link PR to issue #102 @@ -381,4 +381,4 @@ The following documentation files were created as part of tasks 9.4.1-9.4.4: - Timeout configuration explained - Expected behavior for complex Flask apps -All documentation files are located in: `openspec/changes/add-sidecar-flask-support/` +All documentation files are located in: `openspec/changes/sidecar-01-add-sidecar-flask-support/` diff --git a/openspec/changes/add-thorough-codebase-validation/design.md b/openspec/changes/validation-01-add-thorough-codebase-validation/design.md similarity index 100% rename from openspec/changes/add-thorough-codebase-validation/design.md rename to openspec/changes/validation-01-add-thorough-codebase-validation/design.md diff --git a/openspec/changes/add-thorough-codebase-validation/proposal.md b/openspec/changes/validation-01-add-thorough-codebase-validation/proposal.md similarity index 100% rename from openspec/changes/add-thorough-codebase-validation/proposal.md rename to openspec/changes/validation-01-add-thorough-codebase-validation/proposal.md diff --git a/openspec/changes/add-thorough-codebase-validation/specs/codebase-validation-depth/spec.md b/openspec/changes/validation-01-add-thorough-codebase-validation/specs/codebase-validation-depth/spec.md similarity index 100% rename from openspec/changes/add-thorough-codebase-validation/specs/codebase-validation-depth/spec.md rename to openspec/changes/validation-01-add-thorough-codebase-validation/specs/codebase-validation-depth/spec.md diff --git a/openspec/changes/add-thorough-codebase-validation/tasks.md b/openspec/changes/validation-01-add-thorough-codebase-validation/tasks.md similarity index 100% rename from openspec/changes/add-thorough-codebase-validation/tasks.md rename to openspec/changes/validation-01-add-thorough-codebase-validation/tasks.md diff --git a/openspec/config.yaml b/openspec/config.yaml index d827b4a4..db12cae3 100644 --- a/openspec/config.yaml +++ b/openspec/config.yaml @@ -8,7 +8,8 @@ context: | Testing: pytest, CrossHair (symbolic execution), Hypothesis (property-based) Distribution: uvx, PyPI, Docker - Philosophy: Brownfield-first legacy modernization tool. Reverse-engineer contracts from existing code, then enforce to prevent regressions. Offline-first, no vendor lock-in, no cloud dependencies. + Philosophy: Brownfield-first legacy modernization tool. Reverse-engineer contracts from existing code, + then enforce to prevent regressions. Offline-first, no vendor lock-in, no cloud dependencies. Architecture patterns: - Bridge Adapter: Tool-agnostic adapters (GitHub, GitLab, Linear, Jira, Spec-Kit, OpenSpec) @@ -29,20 +30,32 @@ context: | Logging: Use common.logger_setup.get_logger() (avoid print()) Naming: snake_case (files/modules/functions), PascalCase (classes), UPPER_SNAKE_CASE (constants) - Documentation (critical for every change): User-facing docs are published at https://docs.specfact.io (GitHub Pages). Source: docs/ with Jekyll front-matter (layout, title, permalink, description), docs/index.md as landing, docs/_layouts/default.html for sidebar/menu navigation. README.md is the repo entry point. + Documentation (critical for every change): User-facing docs are published at https://docs.specfact.io + (GitHub Pages). Source: docs/ with Jekyll front-matter (layout, title, permalink, description), + docs/index.md as landing, docs/_layouts/default.html for sidebar/menu navigation. README.md is the repo + entry point. - Every change must include documentation research and review: - - (1) Identifies affected documentation: docs/ (reference, guides, adapters, getting-started), README.md, docs/index.md. - - (2) Updates or adds content so docs remain a great resource for new and existing users (learn, adopt, understand). - - (3) If adding or moving pages: ensure front-matter (layout, title, permalink, description) is correct and update docs/_layouts/default.html sidebar navigation so the new or moved page appears in the menu. + - (1) Identifies affected documentation: docs/ (reference, guides, adapters, getting-started), + README.md, docs/index.md. + - (2) Updates or adds content so docs remain a great resource for new and existing users + (learn, adopt, understand). + - (3) If adding or moving pages: ensure front-matter (layout, title, permalink, description) is + correct and update docs/_layouts/default.html sidebar navigation so the new or moved page appears + in the menu. - Docs are published at https://docs.specfact.io (GitHub Pages). - Contract requirements: ALL public APIs MUST have @icontract (@require/@ensure) and @beartype decorators - Testing: Contract-first (primary), minimum 80% coverage, unit/integration/E2E tests required for all changes + Contract requirements: ALL public APIs MUST have @icontract (@require/@ensure) and @beartype + decorators + Testing: Contract-first (primary), minimum 80% coverage, unit/integration/E2E tests required for all + changes - Development discipline (SDD + TDD): SpecFact CLI adds the validation layer; we develop SpecFact itself using the same discipline to prove it works. Order is strict: + Development discipline (SDD + TDD): SpecFact CLI adds the validation layer; we develop SpecFact itself + using the same discipline to prove it works. Order is strict: - (1) Specs first—spec deltas define behavior (Given/When/Then). - - (2) Tests second—write unit/integration tests from spec scenarios (one or more tests per scenario); run tests and expect failure. - - (3) Code last—implement until tests pass and behavior satisfies the spec. Code must batch (satisfy) both (a) spec scenarios and (b) tests. + - (2) Tests second—write unit/integration tests from spec scenarios (one or more tests per scenario); + run tests and expect failure. + - (3) Code last—implement until tests pass and behavior satisfies the spec. Code must batch (satisfy) + both (a) spec scenarios and (b) tests. - If the pattern does not work in practice, adjust the process until it does. # Per-artifact rules (only injected into matching artifacts) @@ -55,10 +68,18 @@ rules: - Address offline-first constraint (no cloud dependencies) - Include rollback plan for risky changes - Check for conflicts with existing bridge adapters or plugin registry - - "Documentation impact (required for every change): Consider effect on docs published at https://docs.specfact.io. Identify affected areas: docs/ (reference, guides, adapters, getting-started), docs/index.md, README.md, docs/_layouts/default.html (sidebar/navigation). - - If the change is user-facing or alters API/CLI behavior, state in Impact which docs will be updated or added so new and existing users can learn, adopt, and understand the change." - - "For public-facing changes, include Source Tracking section with GitHub issue reference (format: ## Source Tracking with - **GitHub Issue**: #, - **Issue URL**: , - **Repository**: /, - **Last Synced Status**: ). - - After creation, update proposal.md Source Tracking section with issue number, URL, repository, and status." + - |- + Documentation impact (required for every change): Consider effect on docs published at + https://docs.specfact.io. Identify affected areas: docs/ (reference, guides, adapters, + getting-started), docs/index.md, README.md, docs/_layouts/default.html (sidebar/navigation). + - If the change is user-facing or alters API/CLI behavior, state in Impact which docs will be + updated or added so new and existing users can learn, adopt, and understand the change. + - |- + For public-facing changes, include Source Tracking section with GitHub issue reference + (format: ## Source Tracking with - **GitHub Issue**: #, - **Issue URL**: , + - **Repository**: /, - **Last Synced Status**: ). + - After creation, update proposal.md Source Tracking section with issue number, URL, repository, + and status. - Source tracking: Only track public repos (specfact-cli, platform-frontend). Skip for internal repos (specfact-cli-internal) specs: @@ -77,29 +98,42 @@ rules: - Include fallback strategies for offline scenarios tasks: - - Enforce SDD+TDD order: - - (1) Branch creation (first). - - (2) Write/add spec deltas if not already done. - - (3) Write tests from spec scenarios—translate each Given/When/Then scenario into test cases; run tests and expect failure (no implementation yet). - - (4) Implement code until tests pass and behavior satisfies the spec; code must batch (satisfy) both (a) spec scenarios and (b) tests. - - (5) Quality gates (format, lint, type-check). - - (6) Documentation research and review (see below). - - (7) PR creation (last). - - "Documentation research and review (required for every change): Include a task that: - - (1) Identifies affected documentation: docs/ (reference, guides, adapters, getting-started), README.md, docs/index.md. - - (2) Updates or adds content so docs remain a great resource for new and existing users (learn, adopt, understand). - - (3) If adding or moving pages: ensure front-matter (layout, title, permalink, description) is correct and update docs/_layouts/default.html sidebar navigation so the new or moved page appears in the menu. - - Docs are published at https://docs.specfact.io (GitHub Pages)." + - Enforce SDD+TDD order: + - (1) Branch creation (first). + - (2) Write/add spec deltas if not already done. + - (3) Write tests from spec scenarios—translate each Given/When/Then scenario into test cases; + run tests and expect failure (no implementation yet). + - (4) Implement code until tests pass and behavior satisfies the spec; code must batch (satisfy) + both (a) spec scenarios and (b) tests. + - (5) Quality gates (format, lint, type-check). + - (6) Documentation research and review (see below). + - (7) PR creation (last). + - |- + Documentation research and review (required for every change): Include a task that: + - (1) Identifies affected documentation: docs/ (reference, guides, adapters, getting-started), + README.md, docs/index.md. + - (2) Updates or adds content so docs remain a great resource for new and existing users + (learn, adopt, understand). + - (3) If adding or moving pages: ensure front-matter (layout, title, permalink, description) is + correct and update docs/_layouts/default.html sidebar navigation so the new or moved page + appears in the menu. + - Docs are published at https://docs.specfact.io (GitHub Pages). - Break into 2-hour maximum chunks - Include contract decorator tasks (@icontract, @beartype) for all public APIs - - Test tasks MUST come before implementation tasks: write tests derived from specs first, then implement. Do not implement before tests exist for the changed behavior. + - >- + Test tasks MUST come before implementation tasks: write tests derived from specs first, then + implement. Do not implement before tests exist for the changed behavior. - Include quality gate tasks: format, lint, type-check, test coverage - Reference existing test patterns in tests/unit/, tests/integration/, tests/e2e/ - - "Version and changelog (required before PR): Include a task that - - (1) bumps patch version when the change is a fix, or minor/major per semver when adding features or breaking; - - (2) syncs version in pyproject.toml, setup.py, src/__init__.py, src/specfact_cli/__init__.py; - - (3) adds a CHANGELOG.md entry under a new [X.Y.Z] - YYYY-MM-DD section with Fixed/Added/Changed as appropriate. - - Place this task after quality gates and documentation, before PR creation." + - |- + Version and changelog (required before PR): Include a task that + - (1) bumps patch version when the change is a fix, or minor/major per semver when adding + features or breaking; + - (2) syncs version in pyproject.toml, setup.py, src/__init__.py, + src/specfact_cli/__init__.py; + - (3) adds a CHANGELOG.md entry under a new [X.Y.Z] - YYYY-MM-DD section with Fixed/Added/Changed + as appropriate. + - Place this task after quality gates and documentation, before PR creation. - Include git workflow tasks: branch creation (first task), PR creation (last task) - For public-facing changes in public repos (specfact-cli, platform-frontend): - Include GitHub issue creation task with format: diff --git a/pyproject.toml b/pyproject.toml index 168a1cb7..5eec8f8b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "specfact-cli" -version = "0.26.16" +version = "0.26.17" description = "Brownfield-first CLI: Reverse engineer legacy Python → specs → enforced contracts. Automate legacy code documentation and prevent modernization regressions." readme = "README.md" requires-python = ">=3.11" diff --git a/setup.py b/setup.py index 3e64b21e..8d7568ee 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ if __name__ == "__main__": _setup = setup( name="specfact-cli", - version="0.26.16", + version="0.26.17", description="SpecFact CLI - Spec -> Contract -> Sentinel tool for contract-driven development", packages=find_packages(where="src"), package_dir={"": "src"}, diff --git a/src/__init__.py b/src/__init__.py index 2fc0e6a2..13b7517a 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -3,4 +3,4 @@ """ # Package version: keep in sync with pyproject.toml, setup.py, src/specfact_cli/__init__.py -__version__ = "0.26.16" +__version__ = "0.26.17" diff --git a/src/specfact_cli/__init__.py b/src/specfact_cli/__init__.py index 4debe5aa..65cecab6 100644 --- a/src/specfact_cli/__init__.py +++ b/src/specfact_cli/__init__.py @@ -9,6 +9,6 @@ - Validating reproducibility """ -__version__ = "0.26.16" +__version__ = "0.26.17" __all__ = ["__version__"] diff --git a/src/specfact_cli/analyzers/ambiguity_scanner.py b/src/specfact_cli/analyzers/ambiguity_scanner.py index 88786d12..43f6f046 100644 --- a/src/specfact_cli/analyzers/ambiguity_scanner.py +++ b/src/specfact_cli/analyzers/ambiguity_scanner.py @@ -10,7 +10,7 @@ import ast import re from dataclasses import dataclass -from enum import Enum +from enum import StrEnum from pathlib import Path from beartype import beartype @@ -19,7 +19,7 @@ from specfact_cli.models.plan import PlanBundle -class AmbiguityStatus(str, Enum): +class AmbiguityStatus(StrEnum): """Ambiguity status levels.""" CLEAR = "Clear" @@ -27,7 +27,7 @@ class AmbiguityStatus(str, Enum): MISSING = "Missing" -class TaxonomyCategory(str, Enum): +class TaxonomyCategory(StrEnum): """Taxonomy categories for ambiguity detection.""" FUNCTIONAL_SCOPE = "Functional Scope & Behavior" @@ -910,12 +910,8 @@ def _extract_target_users(self, plan_bundle: PlanBundle) -> list[str]: # Look for role/permission constants (e.g., ADMIN = "admin") if ( "role" in attr_name or "permission" in attr_name - ) and isinstance(item.value, (ast.Str, ast.Constant)): - role_value = ( - item.value.s - if isinstance(item.value, ast.Str) - else item.value - ) + ) and isinstance(item.value, ast.Constant): + role_value = item.value.value if isinstance(role_value, str) and len(role_value) > 2: role_clean = role_value.strip().lower() if ( diff --git a/src/specfact_cli/commands/backlog_commands.py b/src/specfact_cli/commands/backlog_commands.py index 0f6462cf..032ce335 100644 --- a/src/specfact_cli/commands/backlog_commands.py +++ b/src/specfact_cli/commands/backlog_commands.py @@ -168,8 +168,8 @@ def _load_standup_config() -> dict[str, Any]: with open(path, encoding="utf-8") as f: data = yaml.safe_load(f) or {} config = dict(data.get("standup", data)) - except Exception: - pass + except Exception as exc: + debug_log_operation("config_load", str(path), "error", error=repr(exc)) break if os.environ.get("SPECFACT_STANDUP_STATE"): config["default_state"] = os.environ["SPECFACT_STANDUP_STATE"] @@ -203,8 +203,8 @@ def _load_backlog_config() -> dict[str, Any]: config = dict(nested) if isinstance(nested, dict) else {} else: config = dict(data) if isinstance(data, dict) else {} - except Exception: - pass + except Exception as exc: + debug_log_operation("config_load", str(path), "error", error=repr(exc)) break return config @@ -378,20 +378,66 @@ def _format_daily_item_detail(item: BacklogItem, comments: list[str]) -> str: return "\n".join(parts) +def _collect_comment_annotations( + adapter: str, + items: list[BacklogItem], + *, + repo_owner: str | None, + repo_name: str | None, + github_token: str | None, + ado_org: str | None, + ado_project: str | None, + ado_token: str | None, +) -> dict[str, list[str]]: + """ + Collect comment annotations for backlog items when the adapter supports get_comments(). + + Returns a mapping of item ID -> list of comment strings. Returns empty dict if not supported. + """ + comments_by_item_id: dict[str, list[str]] = {} + try: + adapter_kwargs = _build_adapter_kwargs( + adapter, + repo_owner=repo_owner, + repo_name=repo_name, + github_token=github_token, + ado_org=ado_org, + ado_project=ado_project, + ado_token=ado_token, + ) + registry = AdapterRegistry() + adapter_instance = registry.get_adapter(adapter, **adapter_kwargs) + if not isinstance(adapter_instance, BacklogAdapter): + return comments_by_item_id + get_comments_fn = getattr(adapter_instance, "get_comments", None) + if not callable(get_comments_fn): + return comments_by_item_id + for item in items: + with contextlib.suppress(Exception): + raw = get_comments_fn(item) + comments_by_item_id[item.id] = list(raw) if isinstance(raw, list) else [] + except Exception: + return comments_by_item_id + return comments_by_item_id + + @beartype def _build_copilot_export_content( items: list[BacklogItem], include_value_score: bool = False, + include_comments: bool = False, + comments_by_item_id: dict[str, list[str]] | None = None, ) -> str: """ Build Markdown content for Copilot export: one section per item. Per item: ID, title, status, assignees, last updated, progress summary (standup fields), - blockers, and optionally value score. + blockers, optional value score, and optionally description/comments when enabled. """ lines: list[str] = [] lines.append("# Daily standup – Copilot export") lines.append("") + comments_map = comments_by_item_id or {} for item in items: lines.append(f"## {item.id} - {item.title}") lines.append("") @@ -402,11 +448,26 @@ def _build_copilot_export_content( item.updated_at.strftime("%Y-%m-%d %H:%M") if hasattr(item.updated_at, "strftime") else str(item.updated_at) ) lines.append(f"- **Last updated:** {updated}") + if include_comments: + body = (item.body_markdown or "").strip() + if body: + snippet = body[:_SUMMARIZE_BODY_TRUNCATE] + if len(body) > _SUMMARIZE_BODY_TRUNCATE: + snippet += "\n..." + lines.append("- **Description:**") + for line in snippet.splitlines(): + lines.append(f" {line}" if line else " ") yesterday, today, blockers = _parse_standup_from_body(item.body_markdown or "") if yesterday or today: lines.append(f"- **Progress:** Yesterday: {yesterday or '—'}; Today: {today or '—'}") if blockers: lines.append(f"- **Blockers:** {blockers}") + if include_comments: + item_comments = comments_map.get(item.id, []) + if item_comments: + lines.append("- **Comments (annotations):**") + for c in item_comments: + lines.append(f" - {c}") if item.story_points is not None: lines.append(f"- **Story points:** {item.story_points}") if item.priority is not None: @@ -428,19 +489,25 @@ def _build_summarize_prompt_content( filter_context: dict[str, Any], include_value_score: bool = False, comments_by_item_id: dict[str, list[str]] | None = None, + include_comments: bool = False, ) -> str: """ Build prompt content for standup summary: instruction + filter context + per-item data. - Includes body (description) and annotations (comments) per item so an LLM can produce - a meaningful summary. For use with slash command (e.g. specfact.daily) or copy-paste to Copilot. + When include_comments is True, includes body (description) and annotations (comments) per item + so an LLM can produce a meaningful summary. When False, only metadata (id, title, status, + assignees, last updated) is included to avoid leaking sensitive or large context. + For use with slash command (e.g. specfact.daily) or copy-paste to Copilot. """ lines: list[str] = [] lines.append("--- BEGIN STANDUP PROMPT ---") lines.append("Generate a concise daily standup summary from the following data.") - lines.append( - "Include: current focus, blockers, and pending items. Use each item's description and comments for context. Keep it short and actionable." - ) + if include_comments: + lines.append( + "Include: current focus, blockers, and pending items. Use each item's description and comments for context. Keep it short and actionable." + ) + else: + lines.append("Include: current focus and pending items from the metadata below. Keep it short and actionable.") lines.append("") lines.append("## Filter context") lines.append(f"- Adapter: {filter_context.get('adapter', '—')}") @@ -449,7 +516,8 @@ def _build_summarize_prompt_content( lines.append(f"- Assignee: {filter_context.get('assignee', '—')}") lines.append(f"- Limit: {filter_context.get('limit', '—')}") lines.append("") - lines.append("## Standup data (with description and comments)") + data_header = "Standup data (with description and comments)" if include_comments else "Standup data (metadata only)" + lines.append(f"## {data_header}") lines.append("") comments_map = comments_by_item_id or {} for item in items: @@ -462,24 +530,25 @@ def _build_summarize_prompt_content( item.updated_at.strftime("%Y-%m-%d %H:%M") if hasattr(item.updated_at, "strftime") else str(item.updated_at) ) lines.append(f"- **Last updated:** {updated}") - body = (item.body_markdown or "").strip() - if body: - snippet = body[:_SUMMARIZE_BODY_TRUNCATE] - if len(body) > _SUMMARIZE_BODY_TRUNCATE: - snippet += "\n..." - lines.append("- **Description:**") - lines.append(snippet) - lines.append("") - yesterday, today, blockers = _parse_standup_from_body(item.body_markdown or "") - if yesterday or today: - lines.append(f"- **Progress:** Yesterday: {yesterday or '—'}; Today: {today or '—'}") - if blockers: - lines.append(f"- **Blockers:** {blockers}") - item_comments = comments_map.get(item.id, []) - if item_comments: - lines.append("- **Comments (annotations):**") - for c in item_comments: - lines.append(f" - {c}") + if include_comments: + body = (item.body_markdown or "").strip() + if body: + snippet = body[:_SUMMARIZE_BODY_TRUNCATE] + if len(body) > _SUMMARIZE_BODY_TRUNCATE: + snippet += "\n..." + lines.append("- **Description:**") + lines.append(snippet) + lines.append("") + yesterday, today, blockers = _parse_standup_from_body(item.body_markdown or "") + if yesterday or today: + lines.append(f"- **Progress:** Yesterday: {yesterday or '—'}; Today: {today or '—'}") + if blockers: + lines.append(f"- **Blockers:** {blockers}") + item_comments = comments_map.get(item.id, []) + if item_comments: + lines.append("- **Comments (annotations):**") + for c in item_comments: + lines.append(f" - {c}") if item.story_points is not None: lines.append(f"- **Story points:** {item.story_points}") if item.priority is not None: @@ -559,7 +628,7 @@ def _run_interactive_daily( console.print(Panel(detail, title=f"Story: {item.id}", border_style="cyan")) if suggest_next and n > 1: - pending = [i for i in items if not i.assignees or item.story_points is not None] + pending = [i for i in items if not i.assignees or i.story_points is not None] if pending: best: BacklogItem | None = None best_score: float = -1.0 @@ -1030,6 +1099,12 @@ def daily( "--copilot-export", help="Write summarized progress per story to a file for Copilot slash-command use during standup.", ), + include_comments: bool = typer.Option( + False, + "--comments", + "--annotations", + help="Include item comments/annotations in summarize/copilot export (adapter must support get_comments).", + ), summarize: bool = typer.Option( False, "--summarize", @@ -1118,10 +1193,28 @@ def daily( console.print("[yellow]No backlog items found.[/yellow]") return + comments_by_item_id: dict[str, list[str]] = {} + if include_comments and (copilot_export is not None or summarize or summarize_to is not None): + comments_by_item_id = _collect_comment_annotations( + adapter, + filtered, + repo_owner=repo_owner, + repo_name=repo_name, + github_token=github_token, + ado_org=ado_org, + ado_project=ado_project, + ado_token=ado_token, + ) + if copilot_export is not None: include_score = suggest_next or bool(standup_config.get("suggest_next")) export_path = Path(copilot_export) - content = _build_copilot_export_content(filtered, include_value_score=include_score) + content = _build_copilot_export_content( + filtered, + include_value_score=include_score, + include_comments=include_comments, + comments_by_item_id=comments_by_item_id or None, + ) export_path.write_text(content, encoding="utf-8") console.print(f"[dim]Exported {len(filtered)} item(s) to {export_path}[/dim]") @@ -1134,32 +1227,12 @@ def daily( "assignee": effective_assignee or "—", "limit": effective_limit, } - comments_by_item_id: dict[str, list[str]] = {} - try: - adapter_kwargs_sum = _build_adapter_kwargs( - adapter, - repo_owner=repo_owner, - repo_name=repo_name, - github_token=github_token, - ado_org=ado_org, - ado_project=ado_project, - ado_token=ado_token, - ) - registry_sum = AdapterRegistry() - adapter_instance_sum = registry_sum.get_adapter(adapter, **adapter_kwargs_sum) - get_comments_fn = getattr(adapter_instance_sum, "get_comments", None) - if callable(get_comments_fn): - for it in filtered: - with contextlib.suppress(Exception): - raw = get_comments_fn(it) - comments_by_item_id[it.id] = list(raw) if isinstance(raw, list) else [] - except Exception: - pass content = _build_summarize_prompt_content( filtered, filter_context=filter_ctx, include_value_score=include_score, comments_by_item_id=comments_by_item_id or None, + include_comments=include_comments, ) if summarize_to: Path(summarize_to).write_text(content, encoding="utf-8") @@ -1245,7 +1318,7 @@ def daily( end_date = dt.strptime(str(sprint_end)[:10], "%Y-%m-%d").date() console.print(f"[dim]{_format_sprint_end_header(end_date)}[/dim]") except (ValueError, TypeError): - pass + console.print("[dim]Sprint end date could not be parsed; header skipped.[/dim]") def _add_standup_rows_to_table(tbl: Table, row_list: list[dict[str, Any]], include_pri: bool) -> None: for r in row_list: diff --git a/src/specfact_cli/generators/report_generator.py b/src/specfact_cli/generators/report_generator.py index 97175e7e..0ea362e5 100644 --- a/src/specfact_cli/generators/report_generator.py +++ b/src/specfact_cli/generators/report_generator.py @@ -3,7 +3,7 @@ from __future__ import annotations import json -from enum import Enum +from enum import StrEnum from pathlib import Path from beartype import beartype @@ -14,7 +14,7 @@ from specfact_cli.utils.structured_io import StructuredFormat, dump_structured_file -class ReportFormat(str, Enum): +class ReportFormat(StrEnum): """Report output format.""" MARKDOWN = "markdown" diff --git a/src/specfact_cli/merge/resolver.py b/src/specfact_cli/merge/resolver.py index 0032bbe3..d1ca5fee 100644 --- a/src/specfact_cli/merge/resolver.py +++ b/src/specfact_cli/merge/resolver.py @@ -8,7 +8,7 @@ from __future__ import annotations from dataclasses import dataclass -from enum import Enum +from enum import StrEnum from typing import Any from beartype import beartype @@ -17,7 +17,7 @@ from specfact_cli.models.project import BundleManifest, ProjectBundle -class MergeStrategy(str, Enum): +class MergeStrategy(StrEnum): """Merge resolution strategy.""" AUTO = "auto" # Automatic resolution based on persona ownership @@ -102,7 +102,7 @@ def resolve( if self._sections_disjoint(ours, theirs): # No conflicts - merge all changes merged = self._merge_sections(base, ours, theirs) - return MergeResolution(merged_bundle=merged, conflicts=[], auto_resolved=0, manual_resolved=0, unresolved=0) + return MergeResolution(merged, [], 0, 0, 0) # Rule 2: Find conflicts and resolve based on persona ownership field_conflicts = self._find_conflicts(base, ours, theirs) @@ -161,11 +161,11 @@ def resolve( conflicts.append(conflict) return MergeResolution( - merged_bundle=merged, - conflicts=conflicts, - auto_resolved=auto_resolved, - manual_resolved=manual_resolved, - unresolved=unresolved, + merged, + conflicts, + auto_resolved, + manual_resolved, + unresolved, ) @beartype diff --git a/src/specfact_cli/models/bridge.py b/src/specfact_cli/models/bridge.py index 59453adc..569288d2 100644 --- a/src/specfact_cli/models/bridge.py +++ b/src/specfact_cli/models/bridge.py @@ -9,7 +9,7 @@ from __future__ import annotations -from enum import Enum +from enum import StrEnum from pathlib import Path from beartype import beartype @@ -19,7 +19,7 @@ from specfact_cli.utils.structured_io import StructuredFormat, dump_structured_file, load_structured_file -class AdapterType(str, Enum): +class AdapterType(StrEnum): """Supported adapter types.""" SPECKIT = "speckit" diff --git a/src/specfact_cli/models/change.py b/src/specfact_cli/models/change.py index 563e95c8..4ef428ff 100644 --- a/src/specfact_cli/models/change.py +++ b/src/specfact_cli/models/change.py @@ -12,7 +12,7 @@ from __future__ import annotations -from enum import Enum +from enum import StrEnum from typing import Any from icontract import ensure, require @@ -22,7 +22,7 @@ from specfact_cli.models.source_tracking import SourceTracking -class ChangeType(str, Enum): +class ChangeType(StrEnum): """Change type for delta specs (tool-agnostic).""" ADDED = "added" diff --git a/src/specfact_cli/models/contract.py b/src/specfact_cli/models/contract.py index f17c0ac6..3de1fa7c 100644 --- a/src/specfact_cli/models/contract.py +++ b/src/specfact_cli/models/contract.py @@ -17,7 +17,7 @@ from __future__ import annotations -from enum import Enum +from enum import StrEnum from pathlib import Path from typing import Any @@ -26,7 +26,7 @@ from pydantic import BaseModel, Field -class ContractStatus(str, Enum): +class ContractStatus(StrEnum): """Contract status levels.""" DRAFT = "draft" # Initial contract, not validated diff --git a/src/specfact_cli/models/deviation.py b/src/specfact_cli/models/deviation.py index 328dc526..3c2dcbc7 100644 --- a/src/specfact_cli/models/deviation.py +++ b/src/specfact_cli/models/deviation.py @@ -7,14 +7,14 @@ from __future__ import annotations -from enum import Enum +from enum import StrEnum from beartype import beartype from icontract import ensure, require from pydantic import BaseModel, Field -class DeviationSeverity(str, Enum): +class DeviationSeverity(StrEnum): """Deviation severity level.""" HIGH = "HIGH" @@ -22,7 +22,7 @@ class DeviationSeverity(str, Enum): LOW = "LOW" -class DeviationType(str, Enum): +class DeviationType(StrEnum): """Type of deviation.""" MISSING_FEATURE = "missing_feature" diff --git a/src/specfact_cli/models/enforcement.py b/src/specfact_cli/models/enforcement.py index 8378aab9..2091abd7 100644 --- a/src/specfact_cli/models/enforcement.py +++ b/src/specfact_cli/models/enforcement.py @@ -1,13 +1,13 @@ """Enforcement configuration models for quality gates.""" -from enum import Enum +from enum import StrEnum from beartype import beartype from icontract import ensure, require from pydantic import BaseModel, Field -class EnforcementAction(str, Enum): +class EnforcementAction(StrEnum): """Actions that can be taken when a deviation is detected.""" BLOCK = "BLOCK" # Fail the validation (exit code 1) @@ -15,7 +15,7 @@ class EnforcementAction(str, Enum): LOG = "LOG" # Only log, no warning (exit code 0) -class EnforcementPreset(str, Enum): +class EnforcementPreset(StrEnum): """Predefined enforcement presets.""" MINIMAL = "minimal" # Log everything, never block diff --git a/src/specfact_cli/models/persona_template.py b/src/specfact_cli/models/persona_template.py index 23bc17d3..42b4e884 100644 --- a/src/specfact_cli/models/persona_template.py +++ b/src/specfact_cli/models/persona_template.py @@ -8,7 +8,7 @@ from __future__ import annotations -from enum import Enum +from enum import StrEnum from typing import Any from beartype import beartype @@ -16,7 +16,7 @@ from pydantic import BaseModel, Field -class SectionType(str, Enum): +class SectionType(StrEnum): """Section type classification.""" REQUIRED = "required" # Must be present in export/import diff --git a/src/specfact_cli/models/project.py b/src/specfact_cli/models/project.py index 8a9ae2fc..6a98f214 100644 --- a/src/specfact_cli/models/project.py +++ b/src/specfact_cli/models/project.py @@ -13,7 +13,7 @@ from collections.abc import Callable from concurrent.futures import ThreadPoolExecutor, as_completed from datetime import UTC, datetime -from enum import Enum +from enum import StrEnum from pathlib import Path from typing import Any @@ -33,7 +33,7 @@ ) -class BundleFormat(str, Enum): +class BundleFormat(StrEnum): """Bundle format types.""" MONOLITHIC = "monolithic" # Single file with all aspects diff --git a/src/specfact_cli/models/task.py b/src/specfact_cli/models/task.py index d50cb0b9..52f8f154 100644 --- a/src/specfact_cli/models/task.py +++ b/src/specfact_cli/models/task.py @@ -7,14 +7,14 @@ from __future__ import annotations -from enum import Enum +from enum import StrEnum from beartype import beartype from icontract import ensure, require from pydantic import BaseModel, Field -class TaskPhase(str, Enum): +class TaskPhase(StrEnum): """Task execution phases.""" SETUP = "setup" # Project structure, dependencies, config @@ -23,7 +23,7 @@ class TaskPhase(str, Enum): POLISH = "polish" # Tests, docs, optimization -class TaskStatus(str, Enum): +class TaskStatus(StrEnum): """Task completion status.""" PENDING = "pending" diff --git a/src/specfact_cli/modes/detector.py b/src/specfact_cli/modes/detector.py index 69ad5a84..6b325989 100644 --- a/src/specfact_cli/modes/detector.py +++ b/src/specfact_cli/modes/detector.py @@ -8,13 +8,13 @@ from __future__ import annotations import os -from enum import Enum +from enum import StrEnum from beartype import beartype from icontract import ensure, require -class OperationalMode(str, Enum): +class OperationalMode(StrEnum): """Operational modes for SpecFact CLI.""" CICD = "cicd" diff --git a/src/specfact_cli/runtime.py b/src/specfact_cli/runtime.py index 5c3d80bd..d348e917 100644 --- a/src/specfact_cli/runtime.py +++ b/src/specfact_cli/runtime.py @@ -12,7 +12,7 @@ import logging import os import sys -from enum import Enum +from enum import StrEnum from logging.handlers import RotatingFileHandler from typing import Any @@ -34,7 +34,7 @@ DEBUG_LOG_FORMAT = "%(asctime)s | %(message)s" -class TerminalMode(str, Enum): +class TerminalMode(StrEnum): """Terminal output modes for Rich Console and Progress.""" GRAPHICAL = "graphical" # Full Rich features (colors, animations) diff --git a/src/specfact_cli/utils/env_manager.py b/src/specfact_cli/utils/env_manager.py index 80f22156..2b10357d 100644 --- a/src/specfact_cli/utils/env_manager.py +++ b/src/specfact_cli/utils/env_manager.py @@ -10,14 +10,14 @@ import shutil from dataclasses import dataclass -from enum import Enum +from enum import StrEnum from pathlib import Path from beartype import beartype from icontract import ensure, require -class EnvManager(str, Enum): +class EnvManager(StrEnum): """Python environment manager types.""" HATCH = "hatch" diff --git a/src/specfact_cli/utils/structured_io.py b/src/specfact_cli/utils/structured_io.py index 7b218074..30caa32c 100644 --- a/src/specfact_cli/utils/structured_io.py +++ b/src/specfact_cli/utils/structured_io.py @@ -6,7 +6,7 @@ import json import threading -from enum import Enum +from enum import StrEnum from pathlib import Path from typing import Any, Optional @@ -16,7 +16,7 @@ from specfact_cli.utils.yaml_utils import YAMLUtils -class StructuredFormat(str, Enum): +class StructuredFormat(StrEnum): """Supported structured data formats.""" YAML = "yaml" diff --git a/src/specfact_cli/validators/sidecar/crosshair_summary.py b/src/specfact_cli/validators/sidecar/crosshair_summary.py index 970c31a1..0c6dc5f5 100644 --- a/src/specfact_cli/validators/sidecar/crosshair_summary.py +++ b/src/specfact_cli/validators/sidecar/crosshair_summary.py @@ -189,10 +189,10 @@ def generate_summary_file( Returns: Path to generated summary file """ - from datetime import datetime + from datetime import UTC, datetime if timestamp is None: - timestamp = datetime.utcnow().strftime("%Y%m%dT%H%M%SZ") + timestamp = datetime.now(UTC).strftime("%Y%m%dT%H%M%SZ") # Ensure reports directory exists (creates parent directories if needed) reports_dir.mkdir(parents=True, exist_ok=True) diff --git a/src/specfact_cli/validators/sidecar/frameworks/django.py b/src/specfact_cli/validators/sidecar/frameworks/django.py index 266247f9..35c13072 100644 --- a/src/specfact_cli/validators/sidecar/frameworks/django.py +++ b/src/specfact_cli/validators/sidecar/frameworks/django.py @@ -199,12 +199,9 @@ def _get_function_name(self, func_node: ast.AST) -> str: @beartype def _extract_string_literal(self, node: ast.AST) -> str | None: - """Extract string literal from AST node.""" - if isinstance(node, ast.Constant): - if isinstance(node.value, str): - return node.value - elif hasattr(ast, "Str") and isinstance(node, ast.Str): - return node.s # type: ignore[attr-defined, deprecated] + """Extract string literal from AST node (Python 3.8+ uses ast.Constant).""" + if isinstance(node, ast.Constant) and isinstance(node.value, str): + return node.value return None @beartype diff --git a/src/specfact_cli/validators/sidecar/frameworks/fastapi.py b/src/specfact_cli/validators/sidecar/frameworks/fastapi.py index 323da3a2..7e41f277 100644 --- a/src/specfact_cli/validators/sidecar/frameworks/fastapi.py +++ b/src/specfact_cli/validators/sidecar/frameworks/fastapi.py @@ -182,12 +182,9 @@ def _extract_route_from_function( @beartype def _extract_string_literal(self, node: ast.AST) -> str | None: - """Extract string literal from AST node.""" - if isinstance(node, ast.Constant): - if isinstance(node.value, str): - return node.value - elif hasattr(ast, "Str") and isinstance(node, ast.Str): - return node.s # type: ignore[attr-defined, deprecated] + """Extract string literal from AST node (Python 3.8+ uses ast.Constant).""" + if isinstance(node, ast.Constant) and isinstance(node.value, str): + return node.value return None @beartype diff --git a/src/specfact_cli/validators/sidecar/frameworks/flask.py b/src/specfact_cli/validators/sidecar/frameworks/flask.py index 14872dd2..5096d573 100644 --- a/src/specfact_cli/validators/sidecar/frameworks/flask.py +++ b/src/specfact_cli/validators/sidecar/frameworks/flask.py @@ -222,12 +222,9 @@ def _extract_route_from_function( @beartype def _extract_string_literal(self, node: ast.AST) -> str | None: - """Extract string literal from AST node.""" - if isinstance(node, ast.Constant): - if isinstance(node.value, str): - return node.value - elif hasattr(ast, "Str") and isinstance(node, ast.Str): - return node.s # type: ignore[attr-defined, deprecated] + """Extract string literal from AST node (Python 3.8+ uses ast.Constant).""" + if isinstance(node, ast.Constant) and isinstance(node.value, str): + return node.value return None @beartype diff --git a/src/specfact_cli/validators/sidecar/models.py b/src/specfact_cli/validators/sidecar/models.py index 30ef1916..d83bd131 100644 --- a/src/specfact_cli/validators/sidecar/models.py +++ b/src/specfact_cli/validators/sidecar/models.py @@ -7,7 +7,7 @@ from __future__ import annotations -from enum import Enum +from enum import StrEnum from pathlib import Path from beartype import beartype @@ -15,7 +15,7 @@ from pydantic import BaseModel, Field -class FrameworkType(str, Enum): +class FrameworkType(StrEnum): """Supported framework types for sidecar validation.""" DJANGO = "django" diff --git a/src/specfact_cli/versioning/analyzer.py b/src/specfact_cli/versioning/analyzer.py index 8c9aea2f..a8930c70 100644 --- a/src/specfact_cli/versioning/analyzer.py +++ b/src/specfact_cli/versioning/analyzer.py @@ -6,7 +6,7 @@ from collections.abc import Iterable from dataclasses import dataclass from datetime import UTC, datetime -from enum import Enum +from enum import StrEnum from pathlib import Path from beartype import beartype @@ -18,7 +18,7 @@ from specfact_cli.utils.bundle_loader import load_project_bundle -class ChangeType(str, Enum): +class ChangeType(StrEnum): """Change categories mapped to SemVer bumps.""" NONE = "none" diff --git a/tests/integration/sync/test_ado_backlog_sync.py b/tests/integration/sync/test_ado_backlog_sync.py index f60153e7..128b71fc 100644 --- a/tests/integration/sync/test_ado_backlog_sync.py +++ b/tests/integration/sync/test_ado_backlog_sync.py @@ -89,7 +89,13 @@ def test_openspec_to_ado_export( mock_patch.assert_called_once() @beartype - def test_ado_to_openspec_import(self, ado_adapter: AdoAdapter, tmp_path: Path) -> None: + @patch.object(AdoAdapter, "_get_work_item_comments", return_value=[]) + def test_ado_to_openspec_import( + self, + mock_get_comments: MagicMock, + ado_adapter: AdoAdapter, + tmp_path: Path, + ) -> None: """Test ADO → OpenSpec import (ADO work item → change proposal).""" from unittest.mock import MagicMock diff --git a/tests/unit/commands/test_backlog_daily.py b/tests/unit/commands/test_backlog_daily.py index 923e7d9b..eb5cecdf 100644 --- a/tests/unit/commands/test_backlog_daily.py +++ b/tests/unit/commands/test_backlog_daily.py @@ -20,6 +20,7 @@ from __future__ import annotations +import re from datetime import UTC, datetime from pathlib import Path from unittest.mock import MagicMock @@ -44,6 +45,12 @@ runner = CliRunner() +def _strip_ansi(text: str) -> str: + """Remove ANSI escape codes from CLI output.""" + ansi_escape = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])") + return ansi_escape.sub("", text) + + def _item( id_: str = "1", title: str = "Item", @@ -388,6 +395,27 @@ def test_copilot_export_idempotent_format(self) -> None: assert "Title" in content assert "- " in content or "* " in content or "\n" in content + def test_copilot_export_includes_description_and_comments_when_enabled(self) -> None: + """When enabled, Copilot export includes description and comment annotations.""" + items = [ + _item( + "1", + "Story one", + state="open", + body_markdown="This is the issue description and context.", + ), + ] + comments_by_id = {"1": ["Comment from Alice: In progress.", "Comment from Bob: Blocked on API."]} + content = _build_copilot_export_content( + items, + include_value_score=False, + include_comments=True, + comments_by_item_id=comments_by_id, + ) + assert "Description" in content and "issue description" in content + assert "Comments" in content or "annotations" in content + assert "In progress" in content and "Blocked on API" in content + class TestFormatDailyItemDetail: """Scenario: Interactive detail view refine-like (13.1).""" @@ -429,6 +457,13 @@ def test_daily_help_shows_summarize(self) -> None: assert result.exit_code == 0 assert "summarize" in result.output.lower() + def test_daily_help_shows_comment_annotations(self) -> None: + """Backlog daily has --comments/--annotations option for exports.""" + result = runner.invoke(app, ["backlog", "daily", "--help-advanced"]) + assert result.exit_code == 0 + output = _strip_ansi(result.output) + assert "--comments" in output or "--annotations" in output + class TestBuildSummarizePromptContent: """Scenario: --summarize outputs prompt with filter context and per-item data (22.1).""" @@ -467,7 +502,7 @@ def test_summarize_prompt_contains_per_item_data(self) -> None: assert "## " in content def test_summarize_prompt_includes_body_and_comments_when_provided(self) -> None: - """Summarize prompt includes description (body) and comments so LLM can create meaningful summary.""" + """Summarize prompt includes description (body) and comments when include_comments=True.""" items = [ _item( "1", @@ -482,11 +517,35 @@ def test_summarize_prompt_includes_body_and_comments_when_provided(self) -> None filter_context={"adapter": "github", "state": "open", "sprint": "—", "assignee": "—", "limit": 20}, include_value_score=False, comments_by_item_id=comments_by_id, + include_comments=True, ) assert "Description" in content and "issue description" in content assert "Comments" in content or "annotations" in content assert "In progress" in content and "Blocked on API" in content + def test_summarize_prompt_metadata_only_when_include_comments_false(self) -> None: + """Summarize prompt omits description and comments when include_comments=False (gated on --comments).""" + items = [ + _item( + "1", + "Story one", + state="open", + body_markdown="This is the issue description and context.", + ), + ] + comments_by_id = {"1": ["Comment from Alice: In progress."]} + content = _build_summarize_prompt_content( + items, + filter_context={"adapter": "github", "state": "open", "sprint": "—", "assignee": "—", "limit": 20}, + include_value_score=False, + comments_by_item_id=comments_by_id, + include_comments=False, + ) + assert "metadata only" in content + assert "issue description" not in content + assert "In progress" not in content + assert "Status:" in content and "Story one" in content + def test_summarize_prompt_has_start_end_markers(self) -> None: """Summarize prompt is wrapped in BEGIN/END markers for extraction or emphasis.""" items = [_item("1", "Story", state="open")]