From cb2e89fc7f3edec63b85ae92dfd17d5e88fceb38 Mon Sep 17 00:00:00 2001 From: Dominikus Nold Date: Fri, 30 Jan 2026 22:22:35 +0100 Subject: [PATCH 1/5] feat: backlog refine --ignore-refined and --id, startup docs (fixes #166) OpenSpec change: improve-backlog-refine-and-cli-startup. Adds --ignore-refined/--no-ignore-refined, --id ; helper _item_needs_refinement; interactive refinement prompt section; version 0.26.15. --- AGENTS.md | 1 + CHANGELOG.md | 19 ++++ docs/guides/backlog-refinement.md | 2 + .../CHANGE_VALIDATION.md | 56 ++++++++++++ .../design.md | 21 +++++ .../proposal.md | 52 +++++++++++ .../specs/backlog-refinement/spec.md | 39 +++++++++ .../tasks.md | 55 ++++++++++++ openspec/specs/backlog-refinement/spec.md | 57 ++++++++++++ pyproject.toml | 2 +- resources/prompts/specfact.backlog-refine.md | 22 +++++ setup.py | 2 +- src/__init__.py | 2 +- src/specfact_cli/__init__.py | 2 +- src/specfact_cli/cli.py | 1 + src/specfact_cli/commands/backlog_commands.py | 86 ++++++++++++++++++- tests/unit/commands/test_backlog_commands.py | 58 ++++++++++++- 17 files changed, 469 insertions(+), 8 deletions(-) create mode 100644 openspec/changes/improve-backlog-refine-and-cli-startup/CHANGE_VALIDATION.md create mode 100644 openspec/changes/improve-backlog-refine-and-cli-startup/design.md create mode 100644 openspec/changes/improve-backlog-refine-and-cli-startup/proposal.md create mode 100644 openspec/changes/improve-backlog-refine-and-cli-startup/specs/backlog-refinement/spec.md create mode 100644 openspec/changes/improve-backlog-refine-and-cli-startup/tasks.md diff --git a/AGENTS.md b/AGENTS.md index ce9f1e6d..e9a6e96e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -43,6 +43,7 @@ - Format only: `hatch run format` - Type check: `hatch run type-check` (basedpyright) - Dev shell: `hatch shell` +- **Faster startup**: Use `specfact --skip-checks ` to skip template and version checks (useful in CI or when security scanning causes delay). ## Coding Style & Naming Conventions diff --git a/CHANGELOG.md b/CHANGELOG.md index de9ac1a7..b58d950c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,25 @@ All notable changes to this project will be documented in this file. --- +## [0.26.15] - 2026-01-30 + +### Added (0.26.15) + +- **Backlog refine: ignore-refined and single-item by ID** (OpenSpec change `improve-backlog-refine-and-cli-startup`, fixes [#166](https://github.com/nold-ai/specfact-cli/issues/166)) + - **`--ignore-refined` / `--no-ignore-refined`**: Default on; when set, only items that need refinement are shown (limit applies to unrefined items). Use `--no-ignore-refined` to include already-refined items. + - **`--id `**: Refine only the backlog item with the given issue or work item ID; exits with error if not found. + - **Helper**: `_item_needs_refinement(item)` in `backlog_commands.py` to decide if an item needs refinement (missing sections or low confidence). + - **Fetch behavior**: When both `--ignore-refined` and `--limit` are set, fetches more candidates (e.g. limit × 5) then filters and slices so limit applies to items needing refinement. + - **Docs**: `docs/guides/backlog-refinement.md` documents `--ignore-refined`, `--no-ignore-refined`, and `--id`; AGENTS.md documents `--skip-checks` for faster startup. + - **Prompt**: `resources/prompts/specfact.backlog-refine.md` adds "Interactive refinement (Copilot mode)" with loop: present story → list ambiguities → ask clarification → re-refine until user approves → then mark done and next story. + - **Startup**: Comment in `cli.py` confirms version line is printed before startup checks. + +### Changed (0.26.15) + +- **Version**: Bumped to 0.26.15; synced in `pyproject.toml`, `setup.py`, `src/__init__.py`, `src/specfact_cli/__init__.py`. + +--- + ## [0.26.14] - 2026-01-29 ### Fixed (0.26.14) diff --git a/docs/guides/backlog-refinement.md b/docs/guides/backlog-refinement.md index 3384a4ad..4614de37 100644 --- a/docs/guides/backlog-refinement.md +++ b/docs/guides/backlog-refinement.md @@ -413,6 +413,8 @@ specfact backlog refine [OPTIONS] - `--search`, `-s` - Search query to filter backlog items - `--template`, `-t` - Target template ID (default: auto-detect) +- `--ignore-refined` / `--no-ignore-refined` - When using `--limit N`, apply limit to items that need refinement (default: ignore already-refined items so you see N items that actually need work) +- `--id` - Refine only the backlog item with the given issue or work item ID - `--auto-accept-high-confidence` - Auto-accept refinements with confidence >= 0.85 - `--bundle`, `-b` - OpenSpec bundle path to import refined items - `--auto-bundle` - Auto-import refined items to OpenSpec bundle diff --git a/openspec/changes/improve-backlog-refine-and-cli-startup/CHANGE_VALIDATION.md b/openspec/changes/improve-backlog-refine-and-cli-startup/CHANGE_VALIDATION.md new file mode 100644 index 00000000..e86c4166 --- /dev/null +++ b/openspec/changes/improve-backlog-refine-and-cli-startup/CHANGE_VALIDATION.md @@ -0,0 +1,56 @@ +# Change Validation Report: improve-backlog-refine-and-cli-startup + +**Validation Date**: 2026-01-30 +**Change Proposal**: [proposal.md](./proposal.md) +**Validation Method**: Dry-run simulation and OpenSpec strict validation + +## Executive Summary + +- **Breaking Changes**: 0 detected +- **Dependent Files**: Limited to backlog_commands.py, cli.py, startup_checks.py, prompt file +- **Impact Level**: Low +- **Validation Result**: Pass +- **User Decision**: N/A (no breaking changes) + +## Breaking Changes Detected + +None. New options (`--ignore-refined`, `--no-ignore-refined`, `--id`) are additive; default `--ignore-refined` improves behavior without breaking existing scripts (scripts can use `--no-ignore-refined` to preserve previous behavior). + +## Dependencies Affected + +- **Critical**: None +- **Recommended**: Tests for new helper and options +- **Optional**: Docs for `--skip-checks`, `--ignore-refined`, `--id` + +## Impact Assessment + +- **Code Impact**: backlog_commands.py (filter logic, new options), cli.py (startup order), startup_checks.py (optional timeout), prompt file (new section) +- **Test Impact**: New unit/integration tests for ignore-refined and --id +- **Documentation Impact**: AGENTS.md or docs; backlog refine reference +- **Release Impact**: Patch (additive, backward compatible) + +## Format Validation + +- **proposal.md Format**: Pass (Why, What Changes, Capabilities, Impact present) +- **tasks.md Format**: Pass (hierarchical tasks, branch creation first, PR last) +- **specs Format**: Pass (ADDED Requirements with #### Scenario blocks) +- **design.md Format**: Pass +- **Config.yaml Compliance**: Pass + +## OpenSpec Validation + +- **Status**: Pass +- **Validation Command**: `openspec validate improve-backlog-refine-and-cli-startup --strict` +- **Issues Found**: 0 (after fixing delta header to ## ADDED Requirements) +- **Re-validated**: Yes + +## Validation Artifacts + +- Plan: `specfact-cli-internal/docs/internal/implementation/2026-01-30-backlog-refine-and-cli-improvements-plan.md` +- Change: `openspec/changes/improve-backlog-refine-and-cli-startup/` + +## Next Steps + +1. Review proposal and tasks +2. Apply change when ready: `/opsx:apply improve-backlog-refine-and-cli-startup` (or legacy `/openspec-apply`) +3. Create GitHub issue in nold-ai/specfact-cli for tracking (optional; update proposal Source Tracking when created) diff --git a/openspec/changes/improve-backlog-refine-and-cli-startup/design.md b/openspec/changes/improve-backlog-refine-and-cli-startup/design.md new file mode 100644 index 00000000..fd704f58 --- /dev/null +++ b/openspec/changes/improve-backlog-refine-and-cli-startup/design.md @@ -0,0 +1,21 @@ +# Design: Improve Backlog Refine and CLI Startup + +## Startup: First Output Before Checks + +- **Current**: Callback runs version line then `print_startup_checks()`. If checks are slow (xagt), the version line may appear but console can feel blocked until checks finish. +- **Change**: Ensure `print_version_line()` (or welcome) is the first console output; then run startup checks. No bridge adapter or multi-repo flow. Optional: add a short timeout (e.g. 3s) to `check_pypi_version()` in `startup_checks.py` so slow networks do not block. + +## Backlog Refine: Ignore-Refined and --id + +- **Ignore-refined**: Extract "needs refinement" logic into a helper (e.g. `_item_needs_refinement(item, detector, registry, template_id, ...)`). After `_fetch_backlog_items`, if `ignore_refined`: filter `items` to those where the helper returns True; then if `limit` is set, `items = items[:limit]`. When both `ignore_refined` and `limit` are set, fetch may need a larger cap (e.g. `limit * 5`) so enough non-refined candidates exist; alternatively fetch without limit and filter then slice. +- **--id**: After fetch (and after ignore-refined filter if applied), if `issue_id` is set: `items = [i for i in items if str(i.id) == str(issue_id)]`. If empty, print error and exit. No adapter API change; post-filter only. + +## Prompt: Interactive Refinement (Copilot) + +- **Scope**: Prompt file only (`resources/prompts/specfact.backlog-refine.md`). No CLI code change for this part. +- **Content**: New section "Interactive refinement (Copilot mode)" that instructs the AI to: (1) present each refined story in a clear format; (2) list ambiguities; (3) ask PO/stakeholders for clarification; (4) re-refine with feedback and repeat until approved; (5) only then mark story done and proceed; (6) use readable formatting (tables, panels, headings) for an enjoyable refinement session. + +## Contract / Testing + +- New helper `_item_needs_refinement` (or equivalent) should be covered by unit tests. +- Integration or e2e: refine with `--ignore-refined --limit N` and with `--id N`; assert expected filtering and exit behavior. diff --git a/openspec/changes/improve-backlog-refine-and-cli-startup/proposal.md b/openspec/changes/improve-backlog-refine-and-cli-startup/proposal.md new file mode 100644 index 00000000..44168600 --- /dev/null +++ b/openspec/changes/improve-backlog-refine-and-cli-startup/proposal.md @@ -0,0 +1,52 @@ +# Change: Improve Backlog Refine and CLI Startup + +## Why + +Four improvements are needed: + +1. **Startup delay**: On machines with security scanning (e.g. xagt), the CLI takes 5–10s before first output. Global startup checks (template validation, PyPI version check) and backlog refine init block the first message. Users need faster feedback (e.g. version line before checks). + +2. **Backlog refine --limit loop**: With `--limit N`, the first N items are processed; already-refined items are skipped in the loop. If the first N are all already refined, the user gets N skips every run—always the same stories. We need `--ignore-refined` (default) so limit applies to items that *need* refinement. + +3. **Focused refinement**: There is no way to refine a single story by ID. Users need `--id ISSUE_ID` for focused refinement. + +4. **Copilot interactive refinement**: The backlog-refine prompt does not instruct the AI to show each story, explain ambiguities, ask for clarification, re-refine until the user approves, then update. The experience should be interactive and stakeholder-friendly (MEB goal) at the prompt level. + +## What Changes + +- **MODIFY** `src/specfact_cli/cli.py` – Ensure first output (version line) before startup checks; optional PyPI timeout. +- **MODIFY** `src/specfact_cli/commands/backlog_commands.py` – Add `--ignore-refined`/`--no-ignore-refined`, `--id`; filter logic so limit applies to items needing refinement when ignore-refined. +- **MODIFY** `src/specfact_cli/utils/startup_checks.py` – Optional timeout for `check_pypi_version()`. +- **MODIFY** `resources/prompts/specfact.backlog-refine.md` – Add interactive refinement (Copilot) section: present story → ambiguities → ask clarification → re-refine until approved → then update. +- **MODIFY** `openspec/specs/backlog-refinement/spec.md` – Add scenarios for ignore-refined and --id. +- **NEW** Tests for ignore-refined and --id behavior. +- **MODIFY** Docs/AGENTS.md – Document `--skip-checks` for startup. + +## Capabilities + +- **backlog-refinement**: Ignore already-refined by default; add --id for single-item refinement; prompt interactive loop (prompt-level). +- **cli-performance**: First output before startup checks; optional PyPI timeout (existing cli-performance spec). + +## Impact + +**Affected Specs**: backlog-refinement, cli-performance (reference only) + +**Affected Code**: + +- `cli.py`, `startup_checks.py`, `backlog_commands.py`, `specfact.backlog-refine.md` + +**Integration Points**: + +- Backlog adapters (unchanged; post-filter by id and needs-refinement). +- Copilot/Cursor prompt consumers (improved prompt text). + +**Breaking Changes**: None. New options; default `--ignore-refined` changes which items count toward limit (behavioral improvement). + +**Documentation**: AGENTS.md or docs for `--skip-checks`; backlog refine docs for `--ignore-refined`, `--no-ignore-refined`, `--id`. + +## Source Tracking + +- **GitHub Issue**: #166 +- **Issue URL**: +- **Repository**: nold-ai/specfact-cli +- **Last Synced Status**: proposed diff --git a/openspec/changes/improve-backlog-refine-and-cli-startup/specs/backlog-refinement/spec.md b/openspec/changes/improve-backlog-refine-and-cli-startup/specs/backlog-refinement/spec.md new file mode 100644 index 00000000..983d410f --- /dev/null +++ b/openspec/changes/improve-backlog-refine-and-cli-startup/specs/backlog-refinement/spec.md @@ -0,0 +1,39 @@ +# backlog-refinement Spec Delta: Improve Backlog Refine and CLI Startup + +## ADDED Requirements + +### Requirement: Ignore Already-Refined Items by Default + +The system SHALL support `--ignore-refined` (default) and `--no-ignore-refined` so that when `--limit N` is used, the limit applies to items that need refinement (already-refined items are excluded from the batch by default). + +#### Scenario: Limit applies to items needing refinement when ignore-refined + +- **GIVEN** the user runs `specfact backlog refine --limit 3` (default `--ignore-refined`) +- **AND** the adapter returns at least 5 items, of which the first 3 are already refined (checkboxes + all required sections or high confidence with no missing fields) +- **WHEN** the command processes items +- **THEN** the system filters out already-refined items, then takes the first 3 that need refinement +- **AND** the user sees up to 3 items that actually require refinement (no loop of the same 3 refined items) + +#### Scenario: No-ignore-refined preserves previous behavior + +- **GIVEN** the user runs `specfact backlog refine --limit 3 --no-ignore-refined` +- **WHEN** the command processes items +- **THEN** the system takes the first 3 items from the fetch and processes them in order +- **AND** already-refined items are skipped in the loop (current behavior) + +### Requirement: Focused Refinement by Issue ID + +The system SHALL support `--id ISSUE_ID` to refine only the backlog item with the given issue or work item ID. + +#### Scenario: Refine single item by ID + +- **GIVEN** the user runs `specfact backlog refine --id 123` (with required adapter options) +- **WHEN** the adapter returns items including item with id 123 +- **THEN** the system filters to only the item with id 123 and refines only that item +- **AND** other items are not processed + +#### Scenario: ID not found + +- **GIVEN** the user runs `specfact backlog refine --id 999` (with required adapter options) +- **WHEN** no item with id 999 is in the fetched set +- **THEN** the system prints a clear error (e.g. "No backlog item with id 999 found") and exits with non-zero status diff --git a/openspec/changes/improve-backlog-refine-and-cli-startup/tasks.md b/openspec/changes/improve-backlog-refine-and-cli-startup/tasks.md new file mode 100644 index 00000000..6cafc15c --- /dev/null +++ b/openspec/changes/improve-backlog-refine-and-cli-startup/tasks.md @@ -0,0 +1,55 @@ +# Tasks: Improve Backlog Refine and CLI Startup + +## TDD / SDD order (enforced) + +Per `openspec/config.yaml`: **tests before code**. For any task that adds or changes behavior: + +1. **Spec deltas** define behavior (Given/When/Then) — already in `changes/.../specs/backlog-refinement/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. + +Do not implement production code for new behavior until the corresponding tests exist and have been run (expecting failure). + +--- + +## 1. Create git 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/improve-backlog-refine-and-cli-startup` +- [x] 1.1.3 Verify branch: `git branch --show-current` + +## 2. Startup: first output before checks + +- [x] 2.1 Verify in `cli.py` that version line (or welcome) is printed before `print_startup_checks()`; add comment if order is correct +- [ ] 2.2 Optional: add timeout (e.g. 3s) to `check_pypi_version()` in `startup_checks.py` +- [x] 2.3 Document `--skip-checks` in AGENTS.md or docs for faster startup in CI/slow environments +- [x] 2.4 Run `hatch run format` and `hatch run type-check`; run contract and unit tests for touched files + +## 3. Backlog refine: ignore-refined and --id (TDD: tests first, then code) + +**TDD for this section:** Write tests from spec scenarios below first; run tests and expect failure; then implement until tests pass. + +- [x] 3.1 **Tests first:** From `changes/.../specs/backlog-refinement/spec.md` scenarios (Limit applies when ignore-refined; No-ignore-refined preserves behavior; Refine single item by ID; ID not found), add unit/integration tests in `tests/unit/commands/test_backlog_commands.py` (e.g. for `_item_needs_refinement` and refine filtering). Run tests: `hatch run smart-test-unit` or target file — **expect failure** (no implementation yet). +- [x] 3.2 Add `ignore_refined: bool = typer.Option(True, "--ignore-refined/--no-ignore-refined", ...)` and `issue_id: str | None = typer.Option(None, "--id", ...)` to refine command in `backlog_commands.py` +- [x] 3.3 Extract "already refined" logic into helper (e.g. `_item_needs_refinement(...)`) returning True if item needs refinement +- [x] 3.4 After fetch: if `ignore_refined`, filter items to those needing refinement; if `limit` set, slice to `items[:limit]`; when both set, consider fetching with larger limit (e.g. limit * 5) or no limit then filter+slice +- [x] 3.5 After fetch (and ignore-refined filter): if `issue_id` set, filter to `[i for i in items if str(i.id) == str(issue_id)]`; if empty, print error and exit +- [x] 3.6 Run tests again; **expect pass**. Then run `hatch run format`, `hatch run type-check`, `hatch run contract-test`, `hatch run smart-test` + +## 4. Prompt: interactive refinement section + +- [x] 4.1 Edit `resources/prompts/specfact.backlog-refine.md`: add section "Interactive refinement (Copilot mode)" with loop: present story → list ambiguities → ask clarification → re-refine until user approves → then mark done and next story; add formatting guidance for readability +- [x] 4.2 Ensure prompt states backlog item is updated only after user approval for that story + +## 5. OpenSpec spec delta and docs + +- [x] 5.1 Merge spec delta from `changes/improve-backlog-refine-and-cli-startup/specs/backlog-refinement/spec.md` into `openspec/specs/backlog-refinement/spec.md` when applying change +- [x] 5.2 Update backlog refine docs (if any) for `--ignore-refined`, `--no-ignore-refined`, `--id` +- [x] 5.3 Update patch version and sync across files (`pyproject.toml`, `setup.py`, `__init__.py`) +- [x] 5.4 Update `CHANGELOG.md` with the new version number and the changes made in this change + +## 6. Validation and PR + +- [x] 6.1 Run `openspec validate improve-backlog-refine-and-cli-startup --strict` +- [x] 6.2 Run `hatch run format`, `hatch run type-check`, `hatch run contract-test`, `hatch run smart-test` +- [ ] 6.3 Create Pull Request from `feature/improve-backlog-refine-and-cli-startup` to `dev` with conventional message and description referencing this change (use `.github/pull_request_template.md` for the PR body) diff --git a/openspec/specs/backlog-refinement/spec.md b/openspec/specs/backlog-refinement/spec.md index 41d05ebd..0dce7356 100644 --- a/openspec/specs/backlog-refinement/spec.md +++ b/openspec/specs/backlog-refinement/spec.md @@ -360,3 +360,60 @@ The system SHALL provide progress feedback during initialization of the `specfac - **AND** the progress should use Rich Progress with time elapsed column - **AND** this provides user feedback during 5-10 second initialization delay (especially important in corporate environments with security scans/firewalls) +### Requirement: Import refined content from temporary file + +The system SHALL support importing refined backlog content from a temporary markdown file (same format as export) when `specfact backlog refine --import-from-tmp` is used, matching items by ID and updating remote backlog via the adapter when `--write` is set. + +#### Scenario: Import refined content from temporary file + +- **GIVEN** a markdown file in the same format as the export from `specfact backlog refine --export-to-tmp` (header, then per-item blocks with `## Item N:`, **ID**, **Body** in ```markdown ... ```, **Acceptance Criteria**) +- **AND** the user runs `specfact backlog refine --import-from-tmp --tmp-file ` with the same adapter and filters as used for export (so the same set of items is fetched) +- **WHEN** the import file exists and is readable +- **THEN** the system parses the file and matches each block to a fetched item by **ID** +- **AND** for each matched item the system updates `body_markdown` and `acceptance_criteria` (and optionally title/metrics) from the parsed block +- **AND** if `--write` is not set, the system prints a preview (e.g. "Would update N items") and does not call the adapter +- **AND** if `--write` is set, the system calls `adapter.update_backlog_item(item, update_fields=[...])` for each updated item and prints a success summary (e.g. "Updated N backlog items") +- **AND** the system does not show "Import functionality pending implementation" + +#### Scenario: Import file not found + +- **GIVEN** the user runs `specfact backlog refine --import-from-tmp` (or with `--tmp-file `) +- **WHEN** the resolved import file does not exist +- **THEN** the system prints an error with the expected path and suggests using `--tmp-file` to specify the path +- **AND** the command exits with non-zero status + +### Requirement: Ignore Already-Refined Items by Default + +The system SHALL support `--ignore-refined` (default) and `--no-ignore-refined` so that when `--limit N` is used, the limit applies to items that need refinement (already-refined items are excluded from the batch by default). + +#### Scenario: Limit applies to items needing refinement when ignore-refined + +- **GIVEN** the user runs `specfact backlog refine --limit 3` (default `--ignore-refined`) +- **AND** the adapter returns at least 5 items, of which the first 3 are already refined (checkboxes + all required sections or high confidence with no missing fields) +- **WHEN** the command processes items +- **THEN** the system filters out already-refined items, then takes the first 3 that need refinement +- **AND** the user sees up to 3 items that actually require refinement (no loop of the same 3 refined items) + +#### Scenario: No-ignore-refined preserves previous behavior + +- **GIVEN** the user runs `specfact backlog refine --limit 3 --no-ignore-refined` +- **WHEN** the command processes items +- **THEN** the system takes the first 3 items from the fetch and processes them in order +- **AND** already-refined items are skipped in the loop (current behavior) + +### Requirement: Focused Refinement by Issue ID + +The system SHALL support `--id ISSUE_ID` to refine only the backlog item with the given issue or work item ID. + +#### Scenario: Refine single item by ID + +- **GIVEN** the user runs `specfact backlog refine --id 123` (with required adapter options) +- **WHEN** the adapter returns items including item with id 123 +- **THEN** the system filters to only the item with id 123 and refines only that item +- **AND** other items are not processed + +#### Scenario: ID not found + +- **GIVEN** the user runs `specfact backlog refine --id 999` (with required adapter options) +- **WHEN** no item with id 999 is in the fetched set +- **THEN** the system prints a clear error (e.g. "No backlog item with id 999 found") and exits with non-zero status diff --git a/pyproject.toml b/pyproject.toml index e7fc64b2..37c8f005 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "specfact-cli" -version = "0.26.14" +version = "0.26.15" 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/resources/prompts/specfact.backlog-refine.md b/resources/prompts/specfact.backlog-refine.md index 5fcc757c..987a021d 100644 --- a/resources/prompts/specfact.backlog-refine.md +++ b/resources/prompts/specfact.backlog-refine.md @@ -69,6 +69,8 @@ Refine backlog items from DevOps tools (GitHub Issues, Azure DevOps, etc.) into - Ambiguous name-only matches will prompt for explicit iteration path - `--release RELEASE` - Filter by release identifier (case-insensitive) - `--limit N` - Maximum number of items to process in this refinement session (caps batch size) +- `--ignore-refined` / `--no-ignore-refined` - When set (default), exclude already-refined items so `--limit` applies to items that need refinement. Use `--no-ignore-refined` to process the first N items in order. +- `--id ISSUE_ID` - Refine only this backlog item (issue or work item ID). Other items are ignored. - `--persona PERSONA` - Filter templates by persona (product-owner, architect, developer) - `--framework FRAMEWORK` - Filter templates by framework (agile, scrum, safe, kanban) @@ -162,6 +164,26 @@ specfact backlog refine $ADAPTER \ - Use `:quit` or `:abort` to cancel the entire session gracefully - Session cancellation shows summary and exits without error +### Interactive refinement (Copilot mode) + +When refining backlog items in Copilot mode (e.g. after export to tmp or during a refinement session), follow this **per-story loop** so the PO and stakeholders can review and approve before any update: + +1. **For each story** (one at a time): + - **Present** the refined story in a clear, readable format: + - Use headings for Title, Body, Acceptance Criteria, Metrics. + - Use tables or panels for structured data so it is easy to scan. + - **List ambiguities** or open questions (e.g. unclear scope, missing acceptance criteria, conflicting assumptions). + - **Ask** the PO and other stakeholders for clarification: "Please review the refined story above. Do you want any changes? Any ambiguities to resolve?" + - **If the user provides feedback**: Re-refine the story incorporating the feedback, then repeat from "Present" for this story. + - **Only when the user explicitly approves** (e.g. "looks good", "approved", "no changes"): Mark this story as done and move to the **next** story. + - **Do not update** the backlog item (or write to the refined file as final) until the user has approved this story. + +2. **Formatting**: + - Use clear headings, bullet lists, and optional tables/panels so refinement sessions are easy to follow and enjoyable. + - Keep each story’s block self-contained so stakeholders can focus on one item at a time. + +3. **Rule**: The backlog item (or exported block) must only be updated/finalized **after** the user has approved the refined content for that story. Then proceed to the next story with the same process. + ### Step 3: Present Results Display refinement results: diff --git a/setup.py b/setup.py index e03e30d1..a3e04d7f 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ if __name__ == "__main__": _setup = setup( name="specfact-cli", - version="0.26.14", + version="0.26.15", 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 aa8d6a59..5d4202ed 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.14" +__version__ = "0.26.15" diff --git a/src/specfact_cli/__init__.py b/src/specfact_cli/__init__.py index 3bc2eb64..0c49b21b 100644 --- a/src/specfact_cli/__init__.py +++ b/src/specfact_cli/__init__.py @@ -9,6 +9,6 @@ - Validating reproducibility """ -__version__ = "0.26.14" +__version__ = "0.26.15" __all__ = ["__version__"] diff --git a/src/specfact_cli/cli.py b/src/specfact_cli/cli.py index c0cd7f0d..b89c5bf0 100644 --- a/src/specfact_cli/cli.py +++ b/src/specfact_cli/cli.py @@ -454,6 +454,7 @@ def cli_main() -> None: console.print() # Empty line after banner elif not is_help_or_version and not is_test_mode: # Show simple version line like other CLIs (skip for help/version commands and in test mode) + # Printed before startup checks so users see output immediately (important with slow checks e.g. xagt) print_version_line() # Run startup checks (template validation and version check) diff --git a/src/specfact_cli/commands/backlog_commands.py b/src/specfact_cli/commands/backlog_commands.py index f288b36f..2228a9fd 100644 --- a/src/specfact_cli/commands/backlog_commands.py +++ b/src/specfact_cli/commands/backlog_commands.py @@ -296,6 +296,44 @@ def _parse_refined_export_markdown(content: str) -> dict[str, dict[str, Any]]: return result +@beartype +def _item_needs_refinement( + item: BacklogItem, + detector: TemplateDetector, + registry: TemplateRegistry, + template_id: str | None, + normalized_adapter: str | None, + normalized_framework: str | None, + normalized_persona: str | None, +) -> bool: + """ + Return True if the item needs refinement (should be processed); False if already refined (skip). + + Mirrors the "already refined" skip logic used in the refine loop: checkboxes + all required + sections, or high confidence with no missing fields. + """ + detection_result = detector.detect_template( + item, + provider=normalized_adapter, + framework=normalized_framework, + persona=normalized_persona, + ) + if detection_result.template_id: + target = registry.get_template(detection_result.template_id) if detection_result.template_id else None + if target and target.required_sections: + has_checkboxes = bool( + re.search(r"^[\s]*- \[[ x]\]", item.body_markdown or "", re.MULTILINE | re.IGNORECASE) + ) + all_present = all( + bool(re.search(rf"^#+\s+{re.escape(s)}\s*$", item.body_markdown or "", re.MULTILINE | re.IGNORECASE)) + for s in target.required_sections + ) + if has_checkboxes and all_present and not detection_result.missing_fields: + return False + already_refined = template_id is None and detection_result.confidence >= 0.8 and not detection_result.missing_fields + return not already_refined + + def _fetch_backlog_items( adapter_name: str, search_query: str | None = None, @@ -424,6 +462,16 @@ def refine( "--limit", help="Maximum number of items to process in this refinement session. Use to cap batch size and avoid processing too many items at once.", ), + ignore_refined: bool = typer.Option( + True, + "--ignore-refined/--no-ignore-refined", + help="When set (default), exclude already-refined items from the batch so --limit applies to items that need refinement. Use --no-ignore-refined to process the first N items in order (already-refined skipped in loop).", + ), + issue_id: str | None = typer.Option( + None, + "--id", + help="Refine only this backlog item (issue or work item ID). Other items are ignored.", + ), template_id: str | None = typer.Option(None, "--template", "-t", help="Target template ID (default: auto-detect)"), auto_accept_high_confidence: bool = typer.Option( False, "--auto-accept-high-confidence", help="Auto-accept refinements with confidence >= 0.85" @@ -651,6 +699,10 @@ def refine( init_progress.update(validate_task, description="[green]✓[/green] Configuration validated") # Fetch backlog items with filters + # When ignore_refined and limit are set, fetch more candidates so we have enough after filtering + fetch_limit: int | None = limit + if ignore_refined and limit is not None and limit > 0: + fetch_limit = limit * 5 with Progress( SpinnerColumn(), TextColumn("[progress.description]{task.description}"), @@ -668,7 +720,7 @@ def refine( iteration=iteration, sprint=sprint, release=release, - limit=limit, + limit=fetch_limit, repo_owner=repo_owner, repo_name=repo_name, github_token=github_token, @@ -706,6 +758,34 @@ def refine( console.print("[yellow]No backlog items found.[/yellow]") return + # Filter by issue ID when --id is set + if issue_id is not None: + items = [i for i in items if str(i.id) == str(issue_id)] + if not items: + console.print( + f"[bold red]✗[/bold red] No backlog item with id {issue_id!r} found. " + "Check filters and adapter configuration." + ) + raise typer.Exit(1) + + # When ignore_refined (default), keep only items that need refinement; then apply limit + if ignore_refined: + items = [ + i + for i in items + if _item_needs_refinement( + i, detector, registry, template_id, normalized_adapter, normalized_framework, normalized_persona + ) + ] + if limit is not None and len(items) > limit: + items = items[:limit] + if ignore_refined and (limit is not None or issue_id is not None): + console.print( + f"[dim]Filtered to {len(items)} item(s) needing refinement" + + (f" (limit {limit})" if limit is not None else "") + + "[/dim]" + ) + # Validate export/import flags if export_to_tmp and import_from_tmp: console.print("[bold red]✗[/bold red] --export-to-tmp and --import-from-tmp are mutually exclusive") @@ -843,8 +923,8 @@ def refine( console.print(f"[green]✓ Updated {len(updated_items)} backlog item(s)[/green]") return - # Apply limit if specified - if limit and len(items) > limit: + # Apply limit if specified (when not ignore_refined; when ignore_refined we already filtered and sliced) + if not ignore_refined and limit is not None and len(items) > limit: items = items[:limit] console.print(f"[yellow]Limited to {limit} items (found {len(items)} total)[/yellow]") else: diff --git a/tests/unit/commands/test_backlog_commands.py b/tests/unit/commands/test_backlog_commands.py index 6cfd5319..0d99f9b7 100644 --- a/tests/unit/commands/test_backlog_commands.py +++ b/tests/unit/commands/test_backlog_commands.py @@ -10,9 +10,14 @@ from typer.testing import CliRunner +from specfact_cli.backlog.template_detector import TemplateDetector from specfact_cli.cli import app -from specfact_cli.commands.backlog_commands import _parse_refined_export_markdown +from specfact_cli.commands.backlog_commands import ( + _item_needs_refinement, + _parse_refined_export_markdown, +) from specfact_cli.models.backlog_item import BacklogItem +from specfact_cli.templates.registry import BacklogTemplate, TemplateRegistry runner = CliRunner() @@ -329,3 +334,54 @@ def foo(): assert "return 42" in body assert "```" in body assert "Then we see the error." in body + + +class TestItemNeedsRefinement: + """Tests for _item_needs_refinement helper.""" + + def test_needs_refinement_when_missing_sections(self) -> None: + """Item needs refinement when required sections are missing.""" + registry = TemplateRegistry() + registry.register_template( + BacklogTemplate( + template_id="user-story", + name="User Story", + description="", + required_sections=["As a", "I want", "Acceptance Criteria"], + ) + ) + detector = TemplateDetector(registry) + item = BacklogItem( + id="1", + provider="github", + url="https://github.com/org/repo/issues/1", + title="Story", + body_markdown="As a user I want...", + state="open", + assignees=[], + ) + assert _item_needs_refinement(item, detector, registry, None, "github", None, None) is True + + def test_does_not_need_refinement_when_high_confidence_no_missing(self) -> None: + """Item does not need refinement when confidence >= 0.8 and no missing fields.""" + registry = TemplateRegistry() + registry.register_template( + BacklogTemplate( + template_id="user-story", + name="User Story", + description="", + required_sections=["Acceptance Criteria"], + ) + ) + detector = TemplateDetector(registry) + item = BacklogItem( + id="2", + provider="github", + url="https://github.com/org/repo/issues/2", + title="Story", + body_markdown="As a user I want X.\n\n## Acceptance Criteria\n- [ ] Done", + state="open", + assignees=[], + ) + result = _item_needs_refinement(item, detector, registry, None, "github", None, None) + assert result is False From fc739c32c46e181da954e2832a9f4cee64e6d236 Mon Sep 17 00:00:00 2001 From: Dominikus Nold Date: Fri, 30 Jan 2026 22:27:11 +0100 Subject: [PATCH 2/5] Add change for this branch and improve change create workflow --- .../commands/wf-create-change-from-plan.md | 43 +++++++++++++++---- .../proposal.md | 0 .../specs/backlog-refinement/spec.md | 0 .../tasks.md | 38 ++++++++++++++++ .../tasks.md | 38 ---------------- .../tasks.md | 2 +- 6 files changed, 73 insertions(+), 48 deletions(-) rename openspec/changes/{implement-backlog-refine-import-from-tmp => archive/2026-01-30-implement-backlog-refine-import-from-tmp}/proposal.md (100%) rename openspec/changes/{implement-backlog-refine-import-from-tmp => archive/2026-01-30-implement-backlog-refine-import-from-tmp}/specs/backlog-refinement/spec.md (100%) create mode 100644 openspec/changes/archive/2026-01-30-implement-backlog-refine-import-from-tmp/tasks.md delete mode 100644 openspec/changes/implement-backlog-refine-import-from-tmp/tasks.md diff --git a/.cursor/commands/wf-create-change-from-plan.md b/.cursor/commands/wf-create-change-from-plan.md index 71de8bb0..cfaee254 100644 --- a/.cursor/commands/wf-create-change-from-plan.md +++ b/.cursor/commands/wf-create-change-from-plan.md @@ -16,6 +16,7 @@ Create an OpenSpec change proposal from a plan document (e.g., documentation imp **Guardrails** +- **Read `openspec/config.yaml`** during the workflow (before or at Step 5) to get project context and the TDD/SDD rules; use them when updating tasks.md so that tests-before-code is enforced. - Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required. - Keep changes tightly scoped to the requested outcome. - Never proceed with ambiguities or conflicts - always ask for clarification interactively. @@ -24,6 +25,7 @@ Create an OpenSpec change proposal from a plan document (e.g., documentation imp - **CRITICAL**: Only create GitHub issues in the target repository specified by the plan. Never create issues in a different repository than the plan's target. - For public-facing changes, always sanitize content before creating GitHub issues. - **CRITICAL Git Workflow**: Always add tasks to create a git branch (feature/bugfix/hotfix based on change-id) BEFORE any code modifications, and create a Pull Request to `dev` branch AFTER all tasks are complete. Never work directly on protected branches (main/dev). Branch naming: `/`. +- **CRITICAL TDD**: Per config.yaml, test tasks MUST come before implementation tasks. Write tests from spec scenarios first; run tests and expect failure; then implement until tests pass. **Workflow Steps** @@ -248,9 +250,9 @@ Execute the `/opsx:ff` command to create all artifacts at once: - **proposal.md**: Must include Why, What Changes, Capabilities, Impact sections. Capabilities section is critical - each capability needs a spec file. - **specs//spec.md**: Use Given/When/Then format for scenarios. Reference existing patterns in openspec/specs/. - **design.md**: Document bridge adapter integration, sequence diagrams for multi-repo flows, contract enforcement strategy. - - **tasks.md**: Break into 2-hour maximum chunks. Include contract decorator tasks, test tasks, quality gate tasks, git workflow tasks (branch creation first, PR creation last). + - **tasks.md**: Break into 2-hour maximum chunks. **Per config.yaml:** Test tasks MUST come before implementation tasks (TDD). Include contract decorator tasks, test tasks, quality gate tasks, git workflow tasks (branch creation first, PR creation last). Step 5.2.4 will add a TDD order section and reorder tasks so tests-before-code is explicit. -5. **Note**: After OPSX completes, Step 5 will add git workflow tasks (branch creation and PR creation) and quality standards if not already included. +5. **Note**: After OPSX completes, Step 5 will read config.yaml, add git workflow tasks (branch creation and PR creation), **enforce TDD-first in tasks.md** (Step 5.2.4), and add quality standards if not already included. **4.3: Extract Change ID** @@ -265,10 +267,12 @@ Execute the `/opsx:ff` command to create all artifacts at once: **5.1: Review Against Project Rules and Config** -1. **Read openspec/config.yaml:** - - Project context (tech stack, constraints, architecture patterns) - - Per-artifact rules (proposal, specs, design, tasks) - - Verify artifacts follow config.yaml rules +1. **Required: Read `openspec/config.yaml`** (in the specfact-cli repo: `openspec/config.yaml`): + - **Project context**: Tech stack, constraints, architecture patterns. + - **Development discipline (SDD + TDD)** in context: (1) Specs first, (2) Tests second—write unit/integration tests from spec scenarios; run tests and **expect failure**, (3) Code last—implement until tests pass. + - **Per-artifact rules**: `rules.tasks` in config.yaml—Enforce SDD+TDD order: (1) Branch creation, (2) Spec deltas, (3) Write tests from spec scenarios; run tests and expect failure (no implementation yet), (4) Implement code until tests pass, (5) Quality gates, (6) Documentation, (7) PR creation. Also: "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." + - Use this context for Step 5.2.4 (TDD enforcement in tasks.md). + - Verify artifacts follow config.yaml rules. 2. **Read and apply rules from `specfact-cli/.cursor/rules/`:** - **spec-fact-cli-rules.mdc**: Problem analysis, centralize logic, testing requirements, contract-first approach @@ -281,6 +285,7 @@ Execute the `/opsx:ff` command to create all artifacts at once: - Proposal includes Source Tracking section (if public-facing change) - Tasks include GitHub issue creation task (if public-facing change in public repo) - Tasks follow 2-hour maximum chunk rule + - **Tasks enforce TDD: test tasks before implementation tasks** (see Step 5.2.4) - All artifacts reference existing architecture patterns where applicable **5.2: Update Tasks with Quality Standards and Git Workflow** @@ -349,7 +354,24 @@ For each task in `tasks.md` (after branch creation task), ensure it includes: - Prerequisite changes - External dependencies -**5.2.4: Add Pull Request Creation Task (LAST TASK)** +**5.2.4: Enforce TDD-first in tasks.md (use config.yaml)** + +**Required:** Use the Development discipline and `rules.tasks` from `openspec/config.yaml` (read in Step 5.1). Ensure tasks.md enforces tests before code. + +1. **Add a "TDD / SDD order (enforced)" section** at the top of `tasks.md` (after the title, before the first numbered task section, e.g. before `## 1. Create git branch`): + - State that per `openspec/config.yaml`, **tests before code** apply to any task that adds or changes behavior. + - List the order: (1) Spec deltas define behavior (Given/When/Then), (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. + - Add: "Do not implement production code for new behavior until the corresponding tests exist and have been run (expecting failure)." + - Use a horizontal rule `---` to separate this block from the numbered tasks. + +2. **For each task section that adds or changes behavior** (e.g. a section that has both "add tests" and "implement" subtasks): + - **Reorder** so that "write tests from spec scenarios" (and "run tests; expect failure") appears **before** any "implement" or "add code" tasks for that behavior. + - If the current order is "implement 3.1, 3.2, 3.3, then add tests 3.4", rewrite to: "**Tests first:** 3.1 Write tests from change spec scenarios (e.g. `changes/.../specs//spec.md`); run tests; **expect failure**. 3.2–3.N Implement (add options, helper, etc.). 3.N+1 Run tests again; **expect pass**; then quality gates." + - Add a short **TDD for this section** reminder in the section heading or first bullet where applicable (e.g. "TDD: tests first, then code"). + +3. **Verify:** Scan tasks.md for any block that has both test tasks and implementation tasks; ensure test tasks come first. Config.yaml: "Test tasks MUST come before implementation tasks." + +**5.2.5: Add Pull Request Creation Task (LAST TASK)** **Add as the LAST task in `tasks.md` (after all implementation tasks are complete):** @@ -924,9 +946,10 @@ Location: openspec/changes// Validation: ✓ OpenSpec validation passed ✓ Markdown linting passed (auto-fixed where possible) - ✓ Project rules applied + ✓ Project rules applied (config.yaml read; TDD-first enforced in tasks.md) ✓ Quality standards integrated ✓ Git workflow tasks added (branch creation + PR creation) + ✓ TDD order section and test-before-code task order applied GitHub Issue (if target repository supports issues): ✓ Issue # created in : @@ -937,7 +960,9 @@ GitHub Issue (if target repository supports issues): Next Steps: 1. Review proposal: openspec/changes//proposal.md 2. Review tasks: openspec/changes//tasks.md - 3. Verify git workflow tasks are included: + 3. Verify TDD and git workflow are reflected: + - tasks.md has "TDD / SDD order (enforced)" section at top + - For behavior changes: test tasks before implementation tasks - First task: Create branch `/` - Last task: Create PR to `dev` branch 4. Apply change when ready: /opsx:apply (or /openspec-apply for legacy) diff --git a/openspec/changes/implement-backlog-refine-import-from-tmp/proposal.md b/openspec/changes/archive/2026-01-30-implement-backlog-refine-import-from-tmp/proposal.md similarity index 100% rename from openspec/changes/implement-backlog-refine-import-from-tmp/proposal.md rename to openspec/changes/archive/2026-01-30-implement-backlog-refine-import-from-tmp/proposal.md diff --git a/openspec/changes/implement-backlog-refine-import-from-tmp/specs/backlog-refinement/spec.md b/openspec/changes/archive/2026-01-30-implement-backlog-refine-import-from-tmp/specs/backlog-refinement/spec.md similarity index 100% rename from openspec/changes/implement-backlog-refine-import-from-tmp/specs/backlog-refinement/spec.md rename to openspec/changes/archive/2026-01-30-implement-backlog-refine-import-from-tmp/specs/backlog-refinement/spec.md diff --git a/openspec/changes/archive/2026-01-30-implement-backlog-refine-import-from-tmp/tasks.md b/openspec/changes/archive/2026-01-30-implement-backlog-refine-import-from-tmp/tasks.md new file mode 100644 index 00000000..8a818e7e --- /dev/null +++ b/openspec/changes/archive/2026-01-30-implement-backlog-refine-import-from-tmp/tasks.md @@ -0,0 +1,38 @@ +# Tasks: Implement backlog refine --import-from-tmp + +## 1. Create git 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/implement-backlog-refine-import-from-tmp` +- [x] 1.1.3 Verify branch: `git branch --show-current` + +## 2. Parser for refined export format + +- [x] 2.1.1 Add function to parse refined markdown (e.g. `_parse_refined_export_markdown(content: str) -> dict[str, dict]` returning id → {body_markdown, acceptance_criteria, title?, ...}) in `backlog_commands.py` or new module `src/specfact_cli/backlog/refine_export_parser.py` +- [x] 2.1.2 Split content by `## Item` or `---` to get per-item blocks +- [x] 2.1.3 From each block extract **ID** (required), **Body** (from ```markdown ... ```), **Acceptance Criteria** (optional), optionally **title** and metrics +- [x] 2.1.4 Add unit tests for parser (export-format sample, multiple items, missing optional fields) +- [x] 2.1.5 Run `hatch run format` and `hatch run type-check` + +## 3. Import branch in backlog refine command + +- [x] 3.1.1 In the `if import_from_tmp:` block, after file-exists check: read file content, call parser, build map id → parsed fields +- [x] 3.1.2 For each item in `items`, if item.id in map: set item.body_markdown, item.acceptance_criteria (and optionally title/metrics) from parsed fields +- [x] 3.1.3 If `--write` is not set: print preview ("Would update N items") and return +- [x] 3.1.4 If `--write` is set: get adapter via _build_adapter_kwargs and adapter_registry.get_adapter; for each updated item call adapter.update_backlog_item(item, update_fields=[...]) with same update_fields logic as interactive refine +- [x] 3.1.5 Print success summary (e.g. "Updated N backlog items") +- [x] 3.1.6 Remove "Import functionality pending implementation" message and TODO +- [x] 3.1.7 Run `hatch run format` and `hatch run type-check` + +## 4. Tests and quality + +- [x] 4.1.1 Add or extend test for refine --import-from-tmp (unit: parser; integration or unit with mock: import flow with --tmp-file and --write) +- [x] 4.1.2 Run `hatch run contract-test` (or `hatch run smart-test`) +- [x] 4.1.3 Run `hatch run lint` +- [x] 4.1.4 Run `openspec validate implement-backlog-refine-import-from-tmp --strict` + +## 5. Documentation and PR + +- [x] 5.1.1 Update CHANGELOG.md with fix entry +- [x] 5.1.2 Ensure help text for --import-from-tmp and --tmp-file is accurate +- [x] 5.1.3 Create Pull Request from feature/implement-backlog-refine-import-from-tmp to dev diff --git a/openspec/changes/implement-backlog-refine-import-from-tmp/tasks.md b/openspec/changes/implement-backlog-refine-import-from-tmp/tasks.md deleted file mode 100644 index 10e310fa..00000000 --- a/openspec/changes/implement-backlog-refine-import-from-tmp/tasks.md +++ /dev/null @@ -1,38 +0,0 @@ -# Tasks: Implement backlog refine --import-from-tmp - -## 1. Create git branch - -- [ ] 1.1.1 Ensure we're on dev and up to date: `git checkout dev && git pull origin dev` -- [ ] 1.1.2 Create branch: `git checkout -b feature/implement-backlog-refine-import-from-tmp` -- [ ] 1.1.3 Verify branch: `git branch --show-current` - -## 2. Parser for refined export format - -- [ ] 2.1.1 Add function to parse refined markdown (e.g. `_parse_refined_export_markdown(content: str) -> dict[str, dict]` returning id → {body_markdown, acceptance_criteria, title?, ...}) in `backlog_commands.py` or new module `src/specfact_cli/backlog/refine_export_parser.py` -- [ ] 2.1.2 Split content by `## Item` or `---` to get per-item blocks -- [ ] 2.1.3 From each block extract **ID** (required), **Body** (from ```markdown ... ```), **Acceptance Criteria** (optional), optionally **title** and metrics -- [ ] 2.1.4 Add unit tests for parser (export-format sample, multiple items, missing optional fields) -- [ ] 2.1.5 Run `hatch run format` and `hatch run type-check` - -## 3. Import branch in backlog refine command - -- [ ] 3.1.1 In the `if import_from_tmp:` block, after file-exists check: read file content, call parser, build map id → parsed fields -- [ ] 3.1.2 For each item in `items`, if item.id in map: set item.body_markdown, item.acceptance_criteria (and optionally title/metrics) from parsed fields -- [ ] 3.1.3 If `--write` is not set: print preview ("Would update N items") and return -- [ ] 3.1.4 If `--write` is set: get adapter via _build_adapter_kwargs and adapter_registry.get_adapter; for each updated item call adapter.update_backlog_item(item, update_fields=[...]) with same update_fields logic as interactive refine -- [ ] 3.1.5 Print success summary (e.g. "Updated N backlog items") -- [ ] 3.1.6 Remove "Import functionality pending implementation" message and TODO -- [ ] 3.1.7 Run `hatch run format` and `hatch run type-check` - -## 4. Tests and quality - -- [ ] 4.1.1 Add or extend test for refine --import-from-tmp (unit: parser; integration or unit with mock: import flow with --tmp-file and --write) -- [ ] 4.1.2 Run `hatch run contract-test` (or `hatch run smart-test`) -- [ ] 4.1.3 Run `hatch run lint` -- [ ] 4.1.4 Run `openspec validate implement-backlog-refine-import-from-tmp --strict` - -## 5. Documentation and PR - -- [ ] 5.1.1 Update CHANGELOG.md with fix entry -- [ ] 5.1.2 Ensure help text for --import-from-tmp and --tmp-file is accurate -- [ ] 5.1.3 Create Pull Request from feature/implement-backlog-refine-import-from-tmp to dev diff --git a/openspec/changes/improve-backlog-refine-and-cli-startup/tasks.md b/openspec/changes/improve-backlog-refine-and-cli-startup/tasks.md index 6cafc15c..27c572fb 100644 --- a/openspec/changes/improve-backlog-refine-and-cli-startup/tasks.md +++ b/openspec/changes/improve-backlog-refine-and-cli-startup/tasks.md @@ -52,4 +52,4 @@ Do not implement production code for new behavior until the corresponding tests - [x] 6.1 Run `openspec validate improve-backlog-refine-and-cli-startup --strict` - [x] 6.2 Run `hatch run format`, `hatch run type-check`, `hatch run contract-test`, `hatch run smart-test` -- [ ] 6.3 Create Pull Request from `feature/improve-backlog-refine-and-cli-startup` to `dev` with conventional message and description referencing this change (use `.github/pull_request_template.md` for the PR body) +- [x] 6.3 Create Pull Request from `feature/improve-backlog-refine-and-cli-startup` to `dev` with conventional message and description referencing this change (use `.github/pull_request_template.md` for the PR body) From e9ef04814268432b7f081f8081ff08685124cfcf Mon Sep 17 00:00:00 2001 From: Dominikus Nold Date: Fri, 30 Jan 2026 22:39:41 +0100 Subject: [PATCH 3/5] Improve refinement prompt and add specification feedback, update docs and add backlog refinement tutorial --- docs/README.md | 3 +- docs/_layouts/default.html | 1 + docs/getting-started/README.md | 1 + .../tutorial-backlog-refine-ai-ide.md | 165 ++++++++++++++++++ docs/guides/ai-ide-workflow.md | 3 + docs/guides/backlog-refinement.md | 12 ++ docs/index.md | 6 +- resources/prompts/specfact.backlog-refine.md | 6 +- 8 files changed, 193 insertions(+), 4 deletions(-) create mode 100644 docs/getting-started/tutorial-backlog-refine-ai-ide.md diff --git a/docs/README.md b/docs/README.md index 772861ca..b0f1c93d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -20,7 +20,8 @@ SpecFact isn't just a technical tool—it's designed for **real-world agile/scru 👉 **[Agile/Scrum Workflows Guide](guides/agile-scrum-workflows.md)** ⭐ **START HERE** - Complete guide to persona-based team collaboration 👉 **[DevOps Backlog Integration](guides/devops-adapter-integration.md)** 🆕 **NEW FEATURE** - Integrate SpecFact into agile DevOps workflows -👉 **[Backlog Refinement Guide](guides/backlog-refinement.md)** 🆕 **NEW FEATURE** - AI-assisted template-driven refinement for standardizing work items +👉 **[Backlog Refinement Guide](guides/backlog-refinement.md)** 🆕 **NEW FEATURE** - AI-assisted template-driven refinement for standardizing work items +👉 **[Tutorial: Backlog Refine with AI IDE](getting-started/tutorial-backlog-refine-ai-ide.md)** 🆕 - End-to-end for agile DevOps: slash prompt, story quality, underspecification, DoR, custom templates --- diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html index 6d14e8b3..691780d5 100644 --- a/docs/_layouts/default.html +++ b/docs/_layouts/default.html @@ -133,6 +133,7 @@

Guides

diff --git a/docs/getting-started/README.md b/docs/getting-started/README.md index 9e3ae1dd..34597183 100644 --- a/docs/getting-started/README.md +++ b/docs/getting-started/README.md @@ -46,6 +46,7 @@ uvx specfact-cli@latest plan init my-project --interactive - 📖 **[Tutorial: Using SpecFact with OpenSpec or Spec-Kit](tutorial-openspec-speckit.md)** ⭐ **NEW** - Complete beginner-friendly tutorial - 📖 **[DevOps Backlog Integration](../guides/devops-adapter-integration.md)** 🆕 **NEW FEATURE** - Integrate SpecFact into agile DevOps workflows - 📖 **[Backlog Refinement](../guides/backlog-refinement.md)** 🆕 **NEW FEATURE** - AI-assisted template-driven refinement for standardizing work items +- 📖 **[Tutorial: Backlog Refine with AI IDE](tutorial-backlog-refine-ai-ide.md)** 🆕 - End-to-end for agile DevOps teams: slash prompt, story quality, underspecification, splitting, DoR, custom templates - 📖 **[Use Cases](../guides/use-cases.md)** - See real-world examples - 📖 **[Command Reference](../reference/commands.md)** - Learn all available commands diff --git a/docs/getting-started/tutorial-backlog-refine-ai-ide.md b/docs/getting-started/tutorial-backlog-refine-ai-ide.md new file mode 100644 index 00000000..ee57f451 --- /dev/null +++ b/docs/getting-started/tutorial-backlog-refine-ai-ide.md @@ -0,0 +1,165 @@ +--- +layout: default +title: Tutorial - Backlog Refine with Your AI IDE +description: Integrate SpecFact CLI backlog refinement with your AI IDE. Improve story quality, underspec/overspec, split stories, fix ambiguities, respect DoR, and use custom template mapping. +permalink: /getting-started/tutorial-backlog-refine-ai-ide/ +--- + +# Tutorial: Backlog Refine with Your AI IDE (Agile DevOps Teams) + +This tutorial walks agile DevOps teams through integrating SpecFact CLI backlog refinement with their AI IDE (Cursor, VS Code + Copilot, Claude Code, etc.) using the interactive slash prompt. You will improve backlog story quality, make informed decisions about underspecification, split stories when too big, fix ambiguities, respect Definition of Ready (DoR), and optionally use custom template mapping for advanced teams. + +**Time**: ~20–30 minutes +**Outcome**: End-to-end flow from raw backlog items to template-compliant, DoR-ready stories via your AI IDE. + +--- + +## What You'll Learn + +- Run `specfact backlog refine` and use the **slash prompt** in your AI IDE for interactive refinement +- Use the **interactive feedback loop**: present story → assess specification level (under-/over-/fit) → list ambiguities → ask clarification → re-refine until approved +- Improve story quality: identify **underspecified** (missing AC, vague scope), **overspecified** (too many sub-steps, implementation detail), or **fit-for-scope** stories +- Decide when to **split** stories that are too big +- Respect **Definition of Ready (DoR)** once defined in your team +- For advanced teams: point to **custom template mapping** (e.g. ADO custom fields) when required + +--- + +## Prerequisites + +- SpecFact CLI installed (`uvx specfact-cli@latest` or `pip install specfact-cli`) +- Access to a backlog (GitHub repo or Azure DevOps project) +- AI IDE with slash commands (Cursor, VS Code + Copilot, etc.) +- Optional: `specfact init --ide cursor` (or your IDE) so the backlog-refine slash command is available + +--- + +## Step 1: Run Backlog Refine and Get Items + +From your repo root (or where your backlog lives): + +```bash +# GitHub: fetch open items that need refinement (default: ignore already-refined) +specfact backlog refine github --repo-owner OWNER --repo-name REPO --search "is:open label:feature" --limit 5 --preview + +# Or export to a temp file for your AI IDE to process (recommended for interactive loop) +specfact backlog refine github --repo-owner OWNER --repo-name REPO --export-to-tmp --search "is:open label:feature" --limit 5 +``` + +- Use `--ignore-refined` (default) so `--limit` applies to items that **need** refinement +- Use `--id ISSUE_ID` to refine a **single** item by ID +- Use `--check-dor` when your team has a DoR config in `.specfact/dor.yaml` + +--- + +## Step 2: Invoke the Slash Prompt in Your AI IDE + +In Cursor, VS Code, or your IDE: + +1. Open the **slash command** for backlog refinement (e.g. `/specfact.backlog-refine` or the equivalent in your IDE). +2. Pass the same arguments you would use in the CLI, for example: + - `/specfact.backlog-refine --adapter github --repo-owner OWNER --repo-name NAME --labels feature --limit 5` + +The AI will use the **SpecFact Backlog Refinement** prompt, which includes: + +- Template-driven refinement (user story, defect, spike, enabler) +- **Interactive refinement (Copilot mode)**: present story → list ambiguities → ask clarification → re-refine until you approve +- **Specification level**: for each story, the AI assesses whether it is **under-specified**, **over-specified**, or **fit for scope and intent**, with evidence (missing AC, vague scope, too many sub-steps, etc.) + +--- + +## Step 3: Use the Interactive Feedback Loop + +For each story, the AI should: + +1. **Present** the refined story (Title, Body, Acceptance Criteria, Metrics) in a clear, scannable format. +2. **Assess specification level**: + - **Under-specified**: Missing acceptance criteria, vague scope, unclear “so that” or user value. List what’s missing. + - **Over-specified**: Too much implementation detail, too many sub-steps for one story, or solution prescribed instead of outcome. Suggest what to trim or move. + - **Fit for scope and intent**: Clear persona, capability, benefit, and testable AC; appropriate size. State briefly why it’s ready. +3. **List ambiguities** or open questions (e.g. conflicting assumptions, unclear priority). +4. **Ask** you (PO/stakeholder): “Do you want any changes? Any ambiguities to resolve? Should this story be split?” +5. **Re-refine** if you give feedback, then repeat from “Present” until you **explicitly approve** (e.g. “looks good”, “approved”). +6. Only after approval: mark the story done and move to the next. Do **not** update the backlog item until that story is approved. + +This loop ensures the DevOps team sees **underspecification** (and over-specification) explicitly and can improve story quality and respect DoR before committing to the backlog. + +--- + +## Step 4: Respect Definition of Ready (DoR) + +If your team uses DoR: + +1. Create or edit `.specfact/dor.yaml` in the repo (e.g. require story_points, priority, business_value, acceptance_criteria). +2. Run refine with `--check-dor`: + + ```bash + specfact backlog refine github --repo-owner OWNER --repo-name REPO --check-dor --labels feature + ``` + +3. In the interactive loop, treat DoR as part of “fit for scope”: if the refined story doesn’t meet DoR (e.g. missing AC or story points), the AI should flag it as under-specified or not ready and suggest what to add. + +--- + +## Step 5: When to Split a Story + +During the loop, if the AI or you identify that a story is **too big** (e.g. multiple capabilities, many sub-steps, or clearly two user outcomes): + +- The AI should state: “This story may be too large; consider splitting by [capability / user outcome / step].” +- You decide: either split into two (or more) stories and refine each separately, or keep as one and trim scope. Only after that decision should the story be marked approved and written back. + +--- + +## Step 6: Write Back (When Ready) + +When you’re satisfied with the refined content: + +```bash +# If you used --export-to-tmp, save the refined file as ...-refined.md, then: +specfact backlog refine github --repo-owner OWNER --repo-name REPO --import-from-tmp --write + +# Or run refine interactively with --write (use with care; confirm each item) +specfact backlog refine github --repo-owner OWNER --repo-name REPO --write --labels feature --limit 3 +``` + +Use `--preview` (default) until you’re confident; use `--write` only when you want to update the remote backlog. + +--- + +## Step 7: Advanced Teams — Custom Template Mapping + +If your team uses **custom fields** (e.g. Azure DevOps custom process templates): + +1. **ADO**: Add a custom field mapping file and point the CLI to it: + + ```bash + specfact backlog refine ado --ado-org ORG --ado-project PROJECT \ + --custom-field-mapping .specfact/templates/backlog/field_mappings/ado_custom.yaml \ + --state Active + ``` + +2. See **[Template Customization](../guides/template-customization.md)** and **[Custom Field Mapping](../guides/custom-field-mapping.md)** for defining templates and mapping ADO fields. +3. The same **interactive loop and specification-level assessment** (under-/over-/fit) apply; the AI should use your template’s required sections when assessing “fit for scope”. + +--- + +## Summary + +| Goal | How | +|-----------------------------|-----| +| Improve story quality | Use the interactive loop; fix under-/over-specification and ambiguities before approving. | +| Know if a story is under/over/fit | AI assesses each story and lists evidence; you decide to add detail, split, or accept. | +| Split stories that are too big | AI suggests splitting when appropriate; you refine each new story separately. | +| Respect DoR | Use `--check-dor` and treat DoR as part of “fit for scope” in the loop. | +| Custom templates / mapping | Use `--custom-field-mapping` (ADO) and custom templates; see Template Customization and Custom Field Mapping guides. | + +--- + +## Related Documentation + +- **[Backlog Refinement Guide](../guides/backlog-refinement.md)** — Full reference: templates, options, export/import, DoR +- **[Story scope and specification level](../guides/backlog-refinement.md#story-scope-and-specification-level)** — Underspecification, over-specification, fit-for-scope +- **[Definition of Ready (DoR)](../guides/backlog-refinement.md#step-45-definition-of-ready-dor-validation-optional)** — DoR configuration and validation +- **[Template Customization](../guides/template-customization.md)** — Custom templates for advanced teams +- **[Custom Field Mapping](../guides/custom-field-mapping.md)** — ADO custom field mapping +- **[IDE Integration](../guides/ide-integration.md)** — Set up slash commands in Cursor, VS Code, etc. diff --git a/docs/guides/ai-ide-workflow.md b/docs/guides/ai-ide-workflow.md index c1891083..7376d8ff 100644 --- a/docs/guides/ai-ide-workflow.md +++ b/docs/guides/ai-ide-workflow.md @@ -76,6 +76,9 @@ Once initialized, the following slash commands are available in your IDE: |---------------|---------|------------------------| | `/specfact.compare` | Compare plans | `specfact plan compare` | | `/specfact.validate` | Validation suite | `specfact repro` | +| `/specfact.backlog-refine` | Backlog refinement (AI IDE interactive loop) | `specfact backlog refine github \| ado` | + +For an end-to-end tutorial on backlog refine with your AI IDE (story quality, underspecification, DoR, custom templates), see **[Tutorial: Backlog Refine with AI IDE](../getting-started/tutorial-backlog-refine-ai-ide.md)**. **Related**: [IDE Integration - Available Slash Commands](ide-integration.md#available-slash-commands) diff --git a/docs/guides/backlog-refinement.md b/docs/guides/backlog-refinement.md index 4614de37..2582369c 100644 --- a/docs/guides/backlog-refinement.md +++ b/docs/guides/backlog-refinement.md @@ -11,6 +11,8 @@ permalink: /guides/backlog-refinement/ This guide explains how to use SpecFact CLI's backlog refinement feature to standardize work items from GitHub Issues, Azure DevOps, and other backlog tools into corporate templates (user stories, defects, spikes, enablers). +**Tutorial**: For an end-to-end walkthrough with your AI IDE (Cursor, VS Code, etc.)—including interactive slash prompt, story quality, underspecification, splitting, and DoR—see **[Tutorial: Backlog Refine with AI IDE](../getting-started/tutorial-backlog-refine-ai-ide.md)**. + ## Overview **Why This Matters**: DevOps teams often create backlog items with informal, unstructured descriptions. Template-driven refinement helps enforce corporate standards while maintaining lossless synchronization with your backlog tools. @@ -172,6 +174,16 @@ specfact backlog refine github --search "is:open" # 4. Ask for confirmation before applying ``` +### Story scope and specification level + +During interactive refinement (e.g. when using the slash prompt in your AI IDE), the team should assess each story’s **specification level** so you can improve quality and respect Definition of Ready: + +- **Under-specified**: Missing acceptance criteria, vague scope, unclear “so that” or user value. The AI should list what’s missing (e.g. “No AC”, “Scope could mean X or Y”) so the team can add detail before approving. +- **Over-specified**: Too much implementation detail, too many sub-steps for one story, or solution prescribed instead of outcome. The AI should suggest what to trim or move so the story stays fit for one sprint or one outcome. +- **Fit for scope and intent**: Clear persona, capability, benefit, and testable AC; appropriate size. The AI should state briefly why it’s ready (and, if you use DoR, that DoR is satisfied). + +Include this assessment in the **interactive feedback loop**: present story → assess under-/over-/fit → list ambiguities → ask clarification → re-refine until the PO/stakeholder approves. That way the DevOps team gets to know if a story is under-/over-specified or actually fitting for scope and intent before updating the backlog. + ### Step 4: Preview and Apply Refinement Once validated, the refinement can be previewed or applied: diff --git a/docs/index.md b/docs/index.md index a271f172..e9c6befc 100644 --- a/docs/index.md +++ b/docs/index.md @@ -21,8 +21,9 @@ SpecFact CLI helps you modernize legacy codebases by automatically extracting sp 1. **[Installation](getting-started/installation.md)** - Get started in 60 seconds 2. **[First Steps](getting-started/first-steps.md)** - Run your first command -3. **[Modernizing Legacy Code](guides/brownfield-engineer.md)** ⭐ **PRIMARY** - Brownfield-first guide -4. **[The Brownfield Journey](guides/brownfield-journey.md)** ⭐ - Complete modernization workflow +3. **[Tutorial: Backlog Refine with AI IDE](getting-started/tutorial-backlog-refine-ai-ide.md)** - Integrate backlog refinement with your AI IDE (agile DevOps) +4. **[Modernizing Legacy Code](guides/brownfield-engineer.md)** ⭐ **PRIMARY** - Brownfield-first guide +5. **[The Brownfield Journey](guides/brownfield-journey.md)** ⭐ - Complete modernization workflow ### Using GitHub Spec-Kit? @@ -59,6 +60,7 @@ SpecFact CLI helps you modernize legacy codebases by automatically extracting sp - **Status Synchronization**: Keep OpenSpec and backlog status in sync - **[Backlog Refinement Guide](guides/backlog-refinement.md)** 🆕 **NEW** - AI-assisted template-driven refinement for standardizing work items + - **[Tutorial: Backlog Refine with AI IDE](getting-started/tutorial-backlog-refine-ai-ide.md)** - End-to-end tutorial for agile DevOps teams (slash prompt, DoR, split stories, underspec/overspec) - **Template Detection**: Automatically detect which template matches a backlog item with priority-based resolution - **AI-Assisted Refinement**: Generate prompts for IDE AI copilots to refine unstructured input - **Confidence Scoring**: Validate refined content and provide confidence scores diff --git a/resources/prompts/specfact.backlog-refine.md b/resources/prompts/specfact.backlog-refine.md index 987a021d..50dd7636 100644 --- a/resources/prompts/specfact.backlog-refine.md +++ b/resources/prompts/specfact.backlog-refine.md @@ -172,8 +172,12 @@ When refining backlog items in Copilot mode (e.g. after export to tmp or during - **Present** the refined story in a clear, readable format: - Use headings for Title, Body, Acceptance Criteria, Metrics. - Use tables or panels for structured data so it is easy to scan. + - **Assess specification level** so the DevOps team knows if the story is ready, under-specified, or over-specified: + - **Under-specified**: Missing acceptance criteria, vague scope, unclear "so that" or user value. List evidence (e.g. "No AC", "Scope could mean X or Y"). Suggest what to add. + - **Over-specified**: Too much implementation detail, too many sub-steps for one story, or solution prescribed instead of outcome. List evidence and suggest what to trim or split. + - **Fit for scope and intent**: Clear persona, capability, benefit, and testable AC; appropriate size. State briefly why it is ready (and, if DoR is in use, that DoR is satisfied). - **List ambiguities** or open questions (e.g. unclear scope, missing acceptance criteria, conflicting assumptions). - - **Ask** the PO and other stakeholders for clarification: "Please review the refined story above. Do you want any changes? Any ambiguities to resolve?" + - **Ask** the PO and other stakeholders for clarification: "Please review the refined story above. Do you want any changes? Any ambiguities to resolve? Should this story be split?" - **If the user provides feedback**: Re-refine the story incorporating the feedback, then repeat from "Present" for this story. - **Only when the user explicitly approves** (e.g. "looks good", "approved", "no changes"): Mark this story as done and move to the **next** story. - **Do not update** the backlog item (or write to the refined file as final) until the user has approved this story. From 8cdf533861d661e69e446e96ffb44c5de44ef5d9 Mon Sep 17 00:00:00 2001 From: Dominikus Nold Date: Fri, 30 Jan 2026 22:47:14 +0100 Subject: [PATCH 4/5] Fix spec update and tasks --- .../CHANGE_VALIDATION.md | 0 .../design.md | 0 .../proposal.md | 13 ++++--------- .../specs/backlog-refinement/spec.md | 2 +- .../tasks.md | 13 +++++++------ openspec/specs/backlog-refinement/spec.md | 3 ++- 6 files changed, 14 insertions(+), 17 deletions(-) rename openspec/changes/{improve-backlog-refine-and-cli-startup => archive/2026-01-30-improve-backlog-refine-and-cli-startup}/CHANGE_VALIDATION.md (100%) rename openspec/changes/{improve-backlog-refine-and-cli-startup => archive/2026-01-30-improve-backlog-refine-and-cli-startup}/design.md (100%) rename openspec/changes/{improve-backlog-refine-and-cli-startup => archive/2026-01-30-improve-backlog-refine-and-cli-startup}/proposal.md (65%) rename openspec/changes/{improve-backlog-refine-and-cli-startup => archive/2026-01-30-improve-backlog-refine-and-cli-startup}/specs/backlog-refinement/spec.md (96%) rename openspec/changes/{improve-backlog-refine-and-cli-startup => archive/2026-01-30-improve-backlog-refine-and-cli-startup}/tasks.md (88%) diff --git a/openspec/changes/improve-backlog-refine-and-cli-startup/CHANGE_VALIDATION.md b/openspec/changes/archive/2026-01-30-improve-backlog-refine-and-cli-startup/CHANGE_VALIDATION.md similarity index 100% rename from openspec/changes/improve-backlog-refine-and-cli-startup/CHANGE_VALIDATION.md rename to openspec/changes/archive/2026-01-30-improve-backlog-refine-and-cli-startup/CHANGE_VALIDATION.md diff --git a/openspec/changes/improve-backlog-refine-and-cli-startup/design.md b/openspec/changes/archive/2026-01-30-improve-backlog-refine-and-cli-startup/design.md similarity index 100% rename from openspec/changes/improve-backlog-refine-and-cli-startup/design.md rename to openspec/changes/archive/2026-01-30-improve-backlog-refine-and-cli-startup/design.md diff --git a/openspec/changes/improve-backlog-refine-and-cli-startup/proposal.md b/openspec/changes/archive/2026-01-30-improve-backlog-refine-and-cli-startup/proposal.md similarity index 65% rename from openspec/changes/improve-backlog-refine-and-cli-startup/proposal.md rename to openspec/changes/archive/2026-01-30-improve-backlog-refine-and-cli-startup/proposal.md index 44168600..3139aebf 100644 --- a/openspec/changes/improve-backlog-refine-and-cli-startup/proposal.md +++ b/openspec/changes/archive/2026-01-30-improve-backlog-refine-and-cli-startup/proposal.md @@ -2,15 +2,10 @@ ## Why -Four improvements are needed: - -1. **Startup delay**: On machines with security scanning (e.g. xagt), the CLI takes 5–10s before first output. Global startup checks (template validation, PyPI version check) and backlog refine init block the first message. Users need faster feedback (e.g. version line before checks). - -2. **Backlog refine --limit loop**: With `--limit N`, the first N items are processed; already-refined items are skipped in the loop. If the first N are all already refined, the user gets N skips every run—always the same stories. We need `--ignore-refined` (default) so limit applies to items that *need* refinement. - -3. **Focused refinement**: There is no way to refine a single story by ID. Users need `--id ISSUE_ID` for focused refinement. - -4. **Copilot interactive refinement**: The backlog-refine prompt does not instruct the AI to show each story, explain ambiguities, ask for clarification, re-refine until the user approves, then update. The experience should be interactive and stakeholder-friendly (MEB goal) at the prompt level. +1. **Startup delay**: CLI can take 5–10s before first output (e.g. under xagt). Users need version line before any checks. +2. **Backlog refine --limit**: With `--limit N`, if the first N items are already refined, the user gets N skips every run. We need `--ignore-refined` (default) so limit applies to items that need refinement. +3. **Focused refinement**: No way to refine one story by ID. Add `--id ISSUE_ID`. +4. **Copilot loop**: Prompt should instruct AI to present story → ambiguities → clarify → re-refine until approved → update (interactive, stakeholder-friendly). ## What Changes diff --git a/openspec/changes/improve-backlog-refine-and-cli-startup/specs/backlog-refinement/spec.md b/openspec/changes/archive/2026-01-30-improve-backlog-refine-and-cli-startup/specs/backlog-refinement/spec.md similarity index 96% rename from openspec/changes/improve-backlog-refine-and-cli-startup/specs/backlog-refinement/spec.md rename to openspec/changes/archive/2026-01-30-improve-backlog-refine-and-cli-startup/specs/backlog-refinement/spec.md index 983d410f..f175fe51 100644 --- a/openspec/changes/improve-backlog-refine-and-cli-startup/specs/backlog-refinement/spec.md +++ b/openspec/changes/archive/2026-01-30-improve-backlog-refine-and-cli-startup/specs/backlog-refinement/spec.md @@ -1,4 +1,4 @@ -# backlog-refinement Spec Delta: Improve Backlog Refine and CLI Startup +# backlog-refinement (delta) ## ADDED Requirements diff --git a/openspec/changes/improve-backlog-refine-and-cli-startup/tasks.md b/openspec/changes/archive/2026-01-30-improve-backlog-refine-and-cli-startup/tasks.md similarity index 88% rename from openspec/changes/improve-backlog-refine-and-cli-startup/tasks.md rename to openspec/changes/archive/2026-01-30-improve-backlog-refine-and-cli-startup/tasks.md index 27c572fb..849a65a3 100644 --- a/openspec/changes/improve-backlog-refine-and-cli-startup/tasks.md +++ b/openspec/changes/archive/2026-01-30-improve-backlog-refine-and-cli-startup/tasks.md @@ -21,7 +21,7 @@ Do not implement production code for new behavior until the corresponding tests ## 2. Startup: first output before checks - [x] 2.1 Verify in `cli.py` that version line (or welcome) is printed before `print_startup_checks()`; add comment if order is correct -- [ ] 2.2 Optional: add timeout (e.g. 3s) to `check_pypi_version()` in `startup_checks.py` +- [x] 2.2 Optional: add timeout (e.g. 3s) to `check_pypi_version()` in `startup_checks.py` - [x] 2.3 Document `--skip-checks` in AGENTS.md or docs for faster startup in CI/slow environments - [x] 2.4 Run `hatch run format` and `hatch run type-check`; run contract and unit tests for touched files @@ -41,12 +41,13 @@ Do not implement production code for new behavior until the corresponding tests - [x] 4.1 Edit `resources/prompts/specfact.backlog-refine.md`: add section "Interactive refinement (Copilot mode)" with loop: present story → list ambiguities → ask clarification → re-refine until user approves → then mark done and next story; add formatting guidance for readability - [x] 4.2 Ensure prompt states backlog item is updated only after user approval for that story -## 5. OpenSpec spec delta and docs +## 5. Docs and release -- [x] 5.1 Merge spec delta from `changes/improve-backlog-refine-and-cli-startup/specs/backlog-refinement/spec.md` into `openspec/specs/backlog-refinement/spec.md` when applying change -- [x] 5.2 Update backlog refine docs (if any) for `--ignore-refined`, `--no-ignore-refined`, `--id` -- [x] 5.3 Update patch version and sync across files (`pyproject.toml`, `setup.py`, `__init__.py`) -- [x] 5.4 Update `CHANGELOG.md` with the new version number and the changes made in this change +Specs are updated only when the change is **archived** (not during apply). Do not add tasks to merge spec delta into main spec during implementation. + +- [x] 5.1 Update backlog refine docs (if any) for `--ignore-refined`, `--no-ignore-refined`, `--id` +- [x] 5.2 Update patch version and sync across files (`pyproject.toml`, `setup.py`, `__init__.py`) +- [x] 5.3 Update `CHANGELOG.md` with the new version number and the changes made in this change ## 6. Validation and PR diff --git a/openspec/specs/backlog-refinement/spec.md b/openspec/specs/backlog-refinement/spec.md index 0dce7356..32051569 100644 --- a/openspec/specs/backlog-refinement/spec.md +++ b/openspec/specs/backlog-refinement/spec.md @@ -366,7 +366,7 @@ The system SHALL support importing refined backlog content from a temporary mark #### Scenario: Import refined content from temporary file -- **GIVEN** a markdown file in the same format as the export from `specfact backlog refine --export-to-tmp` (header, then per-item blocks with `## Item N:`, **ID**, **Body** in ```markdown ... ```, **Acceptance Criteria**) +- **GIVEN** a markdown file in the same format as the export from `specfact backlog refine --export-to-tmp` (header, then per-item blocks with `## Item N:`, **ID**, **Body** in ```markdown ...```, **Acceptance Criteria**) - **AND** the user runs `specfact backlog refine --import-from-tmp --tmp-file ` with the same adapter and filters as used for export (so the same set of items is fetched) - **WHEN** the import file exists and is readable - **THEN** the system parses the file and matches each block to a fetched item by **ID** @@ -417,3 +417,4 @@ The system SHALL support `--id ISSUE_ID` to refine only the backlog item with th - **GIVEN** the user runs `specfact backlog refine --id 999` (with required adapter options) - **WHEN** no item with id 999 is in the fetched set - **THEN** the system prints a clear error (e.g. "No backlog item with id 999 found") and exits with non-zero status + From 87d7511b568ad86814552d091c5f6e794b1ab924 Mon Sep 17 00:00:00 2001 From: Dominikus Nold Date: Fri, 30 Jan 2026 22:52:22 +0100 Subject: [PATCH 5/5] Improve pr orchestrator pipeline triggers --- .github/workflows/pr-orchestrator.yml | 40 ++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pr-orchestrator.yml b/.github/workflows/pr-orchestrator.yml index 93e32080..2931f81a 100644 --- a/.github/workflows/pr-orchestrator.yml +++ b/.github/workflows/pr-orchestrator.yml @@ -6,20 +6,52 @@ on: pull_request: branches: [main, dev] paths-ignore: + - "**/*.md" + - "**/*.mdc" - "docs/**" - - "**.md" - - "**.mdc" push: branches: [main, dev] paths-ignore: + - "**/*.md" + - "**/*.mdc" - "docs/**" - - "**.md" - - "**.mdc" workflow_dispatch: +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: + changes: + name: Detect code changes + runs-on: ubuntu-latest + outputs: + code_changed: ${{ steps.out.outputs.code_changed }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: dorny/paths-filter@v3 + id: filter + with: + filters: | + code: + - '**' + - '!**/*.md' + - '!**/*.mdc' + - '!docs/**' + - id: out + run: | + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + echo "code_changed=true" >> "$GITHUB_OUTPUT" + else + echo "code_changed=${{ steps.filter.outputs.code }}" >> "$GITHUB_OUTPUT" + fi + tests: name: Tests (Python 3.12) + needs: [changes] + if: needs.changes.outputs.code_changed == 'true' outputs: run_unit_coverage: ${{ steps.detect-unit.outputs.run_unit_coverage }} permissions: