devflow-cli 2.2.0__tar.gz → 2.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.gitignore +1 -0
- devflow_cli-2.3.0/.specify/specs/021-review-iterations/checklists/requirements.md +35 -0
- devflow_cli-2.3.0/.specify/specs/021-review-iterations/plan.md +112 -0
- devflow_cli-2.3.0/.specify/specs/021-review-iterations/research.md +42 -0
- devflow_cli-2.3.0/.specify/specs/021-review-iterations/spec.md +143 -0
- devflow_cli-2.3.0/.specify/specs/021-review-iterations/tasks.md +140 -0
- devflow_cli-2.3.0/.specify/specs/022-fix-regen-command/checklists/requirements.md +35 -0
- devflow_cli-2.3.0/.specify/specs/022-fix-regen-command/plan.md +100 -0
- devflow_cli-2.3.0/.specify/specs/022-fix-regen-command/research.md +32 -0
- devflow_cli-2.3.0/.specify/specs/022-fix-regen-command/spec.md +140 -0
- devflow_cli-2.3.0/.specify/specs/022-fix-regen-command/tasks.md +120 -0
- devflow_cli-2.3.0/.specify/specs/023-add-logging/checklists/requirements.md +35 -0
- devflow_cli-2.3.0/.specify/specs/023-add-logging/plan.md +129 -0
- devflow_cli-2.3.0/.specify/specs/023-add-logging/research.md +56 -0
- devflow_cli-2.3.0/.specify/specs/023-add-logging/spec.md +115 -0
- devflow_cli-2.3.0/.specify/specs/023-add-logging/tasks.md +126 -0
- devflow_cli-2.3.0/.specify/specs/024-validate-constants/checklists/requirements.md +35 -0
- devflow_cli-2.3.0/.specify/specs/024-validate-constants/plan.md +79 -0
- devflow_cli-2.3.0/.specify/specs/024-validate-constants/research.md +35 -0
- devflow_cli-2.3.0/.specify/specs/024-validate-constants/spec.md +121 -0
- devflow_cli-2.3.0/.specify/specs/024-validate-constants/tasks.md +90 -0
- devflow_cli-2.3.0/.specify/specs/025-harden-tests/checklists/requirements.md +35 -0
- devflow_cli-2.3.0/.specify/specs/025-harden-tests/plan.md +87 -0
- devflow_cli-2.3.0/.specify/specs/025-harden-tests/research.md +23 -0
- devflow_cli-2.3.0/.specify/specs/025-harden-tests/spec.md +141 -0
- devflow_cli-2.3.0/.specify/specs/025-harden-tests/tasks.md +120 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/CHANGELOG.md +47 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/CLAUDE.md +9 -1
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/PKG-INFO +1 -1
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/commands/devflow.clarify.md +4 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/commands/devflow.contracts.md +4 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/commands/devflow.docs.md +4 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/commands/devflow.plan.md +1 -1
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/commands/devflow.regen.md +3 -3
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/commands/devflow.research.md +4 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/commands/devflow.spec.md +11 -10
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/docs/cli-reference.md +10 -9
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/docs/commands-reference.md +3 -3
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/docs/pipeline.md +2 -2
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/pyproject.toml +1 -1
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/__init__.py +11 -1
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/cli.py +5 -2
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/commands/check.py +4 -1
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/commands/feature.py +4 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/commands/init_cmd.py +5 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/commands/migrate_cmd.py +4 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/commands/migrate_speckit.py +8 -0
- devflow_cli-2.2.0/src/devflow_cli/commands/regen.py → devflow_cli-2.3.0/src/devflow_cli/commands/stale.py +6 -6
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/core/catalog.py +4 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/core/git.py +6 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/core/hooks.py +5 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/core/manifest.py +4 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/core/state.py +11 -2
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/core/validators.py +6 -0
- devflow_cli-2.3.0/src/devflow_cli/utils/logging.py +62 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/utils/paths.py +6 -2
- devflow_cli-2.3.0/tests/test_cmd_check.py +53 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/test_cmd_feature.py +35 -0
- devflow_cli-2.2.0/tests/test_cmd_regen.py → devflow_cli-2.3.0/tests/test_cmd_stale.py +11 -11
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/test_cmd_status.py +11 -0
- devflow_cli-2.3.0/tests/test_constants.py +48 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/test_git.py +22 -0
- devflow_cli-2.3.0/tests/test_logging.py +104 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/test_state.py +156 -1
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/uv.lock +1 -1
- devflow_cli-2.2.0/tests/test_cmd_check.py +0 -25
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.claude/commands/speckit.analyze.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.claude/commands/speckit.checklist.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.claude/commands/speckit.clarify.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.claude/commands/speckit.constitution.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.claude/commands/speckit.implement.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.claude/commands/speckit.plan.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.claude/commands/speckit.specify.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.claude/commands/speckit.tasks.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.claude/commands/speckit.taskstoissues.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.github/workflows/ci.yml +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.github/workflows/release.yml +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/init-options.json +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/memory/constitution.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/scripts/bash/check-prerequisites.sh +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/scripts/bash/common.sh +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/scripts/bash/create-new-feature.sh +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/scripts/bash/setup-plan.sh +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/scripts/bash/update-agent-context.sh +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/001-cli-init-options/checklists/requirements.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/001-cli-init-options/contracts/cli-init.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/001-cli-init-options/data-model.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/001-cli-init-options/plan.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/001-cli-init-options/research.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/001-cli-init-options/spec.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/001-cli-init-options/tasks.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/002-cascade-regen/checklists/requirements.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/002-cascade-regen/contracts/cli-regen.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/002-cascade-regen/contracts/cli-status-staleness.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/002-cascade-regen/data-model.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/002-cascade-regen/plan.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/002-cascade-regen/research.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/002-cascade-regen/spec.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/002-cascade-regen/tasks.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/003-usecase-guides/checklists/requirements.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/003-usecase-guides/data-model.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/003-usecase-guides/plan.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/003-usecase-guides/quickstart.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/003-usecase-guides/research.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/003-usecase-guides/spec.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/003-usecase-guides/tasks.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/004-specify-central-directory/checklists/requirements.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/004-specify-central-directory/contracts/cli-commands.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/004-specify-central-directory/data-model.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/004-specify-central-directory/plan.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/004-specify-central-directory/quickstart.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/004-specify-central-directory/research.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/004-specify-central-directory/spec.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/004-specify-central-directory/tasks.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/005-implement-subphases/checklists/requirements.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/005-implement-subphases/plan.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/005-implement-subphases/quickstart.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/005-implement-subphases/research.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/005-implement-subphases/spec.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/005-implement-subphases/tasks.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/006-template-upgrade/checklists/requirements.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/006-template-upgrade/contracts/cli-upgrade.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/006-template-upgrade/data-model.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/006-template-upgrade/plan.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/006-template-upgrade/quickstart.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/006-template-upgrade/research.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/006-template-upgrade/spec.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/006-template-upgrade/tasks.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/007-project-documentation/checklists/requirements.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/007-project-documentation/data-model.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/007-project-documentation/plan.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/007-project-documentation/quickstart.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/007-project-documentation/research.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/007-project-documentation/spec.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/007-project-documentation/tasks.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/008-hardening-bugs/checklists/requirements.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/008-hardening-bugs/plan.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/008-hardening-bugs/quickstart.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/008-hardening-bugs/research.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/008-hardening-bugs/spec.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/008-hardening-bugs/tasks.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/009-ci-pypi/checklists/requirements.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/009-ci-pypi/plan.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/009-ci-pypi/quickstart.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/009-ci-pypi/research.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/009-ci-pypi/spec.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/009-ci-pypi/tasks.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/010-flexible-pipeline/checklists/requirements.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/010-flexible-pipeline/plan.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/010-flexible-pipeline/quickstart.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/010-flexible-pipeline/research.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/010-flexible-pipeline/spec.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/010-flexible-pipeline/tasks.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/011-cursor-support/checklists/requirements.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/011-cursor-support/plan.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/011-cursor-support/quickstart.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/011-cursor-support/research.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/011-cursor-support/spec.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/011-cursor-support/tasks.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/012-fix-critical-bugs/checklists/requirements.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/012-fix-critical-bugs/plan.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/012-fix-critical-bugs/research.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/012-fix-critical-bugs/spec.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/012-fix-critical-bugs/tasks.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/013-align-truth-sources/checklists/requirements.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/013-align-truth-sources/plan.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/013-align-truth-sources/quickstart.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/013-align-truth-sources/spec.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/013-align-truth-sources/tasks.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/014-enforce-state-machine/checklists/requirements.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/014-enforce-state-machine/plan.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/014-enforce-state-machine/quickstart.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/014-enforce-state-machine/spec.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/014-enforce-state-machine/tasks.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/015-fix-review-contradiction/checklists/requirements.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/015-fix-review-contradiction/plan.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/015-fix-review-contradiction/research.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/015-fix-review-contradiction/spec.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/015-fix-review-contradiction/tasks.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/016-harden-state-machine/checklists/requirements.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/016-harden-state-machine/plan.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/016-harden-state-machine/research.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/016-harden-state-machine/spec.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/016-harden-state-machine/tasks.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/017-fix-robustness-issues/checklists/requirements.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/017-fix-robustness-issues/plan.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/017-fix-robustness-issues/research.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/017-fix-robustness-issues/spec.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/017-fix-robustness-issues/tasks.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/018-fix-final-robustness/spec.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/019-quality-hardening/checklists/requirements.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/019-quality-hardening/data-model.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/019-quality-hardening/plan.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/019-quality-hardening/research.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/019-quality-hardening/spec.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/019-quality-hardening/tasks.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/020-migrate-speckit/checklists/requirements.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/020-migrate-speckit/data-model.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/020-migrate-speckit/plan.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/020-migrate-speckit/quickstart.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/020-migrate-speckit/research.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/020-migrate-speckit/spec.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/specs/020-migrate-speckit/tasks.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/templates/agent-file-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/templates/checklist-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/templates/constitution-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/templates/plan-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/templates/spec-template-brownfield.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/templates/spec-template-greenfield.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/templates/spec-template-microservices.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/templates/spec-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/.specify/templates/tasks-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/CONTRIBUTING.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/LICENSE +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/README.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/agents/devflow-autofix.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/agents/devflow-review.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/commands/devflow.analyze.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/commands/devflow.checklist.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/commands/devflow.constitution.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/commands/devflow.context.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/commands/devflow.extension.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/commands/devflow.implement.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/commands/devflow.init.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/commands/devflow.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/commands/devflow.metrics.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/commands/devflow.review-impl.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/commands/devflow.review-spec.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/commands/devflow.review-tasks.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/commands/devflow.status.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/commands/devflow.sync-linear.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/commands/devflow.tasks-to-issues.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/commands/devflow.tasks.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/docs/cursor-guide.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/docs/guides/brownfield.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/docs/guides/greenfield.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/docs/guides/microservices.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/docs/index.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/docs/spec-driven.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/extensions/EXTENSION-API-REFERENCE.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/extensions/EXTENSION-DEVELOPMENT-GUIDE.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/extensions/README.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/extensions/catalog.community.json +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/extensions/catalog.json +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/extensions/template/example-command.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/extensions/template/example-extension.json +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/commands/__init__.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/commands/context.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/commands/export_cmd.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/commands/extension.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/commands/rollback.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/commands/status.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/commands/upgrade_cmd.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/core/__init__.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/core/installer.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/core/scanner.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/core/staleness.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/utils/__init__.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/utils/console.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/src/devflow_cli/utils/strings.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/agent-context-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/analyze-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/checklist-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/checklists/api.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/checklists/requirements.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/checklists/security.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/checklists/ux.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/clarify-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/constitution-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/contracts/README-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/contracts/api-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/contracts/components-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/contracts/interfaces-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/contracts/services-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/contracts-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/data-model-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/devflow-hooks-template.yml +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/docs-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/export/copilot-instructions-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/export/cursor-rules-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/extension-manifest-template.json +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/plan-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/quickstart-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/research-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/review-impl-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/review-spec-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/review-tasks-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/spec-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/templates/tasks-template.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/conftest.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/fixtures/agents/mock-agent.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/fixtures/commands/mock-command.md +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/fixtures/mock-catalog.json +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/fixtures/mock-state.json +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/run-tests.sh +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/test-community-catalog.sh +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/test-helpers.sh +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/test-template-variants.sh +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/test_catalog.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/test_cmd_context.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/test_cmd_extension.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/test_cmd_init.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/test_cmd_migrate.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/test_cmd_migrate_speckit.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/test_cmd_upgrade.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/test_context.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/test_e2e_pipeline.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/test_hooks.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/test_installer.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/test_integration.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/test_manifest.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/test_paths.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/test_rollback.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/test_scanner.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/test_staleness.py +0 -0
- {devflow_cli-2.2.0 → devflow_cli-2.3.0}/tests/test_validators.py +0 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Specification Quality Checklist: Review Iterations Tracking
|
|
2
|
+
|
|
3
|
+
**Purpose**: Validate specification completeness and quality before proceeding to planning
|
|
4
|
+
**Created**: 2026-03-21
|
|
5
|
+
**Feature**: [spec.md](../spec.md)
|
|
6
|
+
|
|
7
|
+
## Content Quality
|
|
8
|
+
|
|
9
|
+
- [x] No implementation details (languages, frameworks, APIs)
|
|
10
|
+
- [x] Focused on user value and business needs
|
|
11
|
+
- [x] Written for non-technical stakeholders
|
|
12
|
+
- [x] All mandatory sections completed
|
|
13
|
+
|
|
14
|
+
## Requirement Completeness
|
|
15
|
+
|
|
16
|
+
- [x] No [NEEDS CLARIFICATION] markers remain
|
|
17
|
+
- [x] Requirements are testable and unambiguous
|
|
18
|
+
- [x] Success criteria are measurable
|
|
19
|
+
- [x] Success criteria are technology-agnostic (no implementation details)
|
|
20
|
+
- [x] All acceptance scenarios are defined
|
|
21
|
+
- [x] Edge cases are identified
|
|
22
|
+
- [x] Scope is clearly bounded
|
|
23
|
+
- [x] Dependencies and assumptions identified
|
|
24
|
+
|
|
25
|
+
## Feature Readiness
|
|
26
|
+
|
|
27
|
+
- [x] All functional requirements have clear acceptance criteria
|
|
28
|
+
- [x] User scenarios cover primary flows
|
|
29
|
+
- [x] Feature meets measurable outcomes defined in Success Criteria
|
|
30
|
+
- [x] No implementation details leak into specification
|
|
31
|
+
|
|
32
|
+
## Notes
|
|
33
|
+
|
|
34
|
+
- Spec references specific code locations (state.py, __init__.py) in "Comportement existant" section — this is acceptable for brownfield specs documenting current behavior, not implementation prescription.
|
|
35
|
+
- No [NEEDS CLARIFICATION] markers — the feature scope is narrow and well-defined.
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Implementation Plan: Review Iterations Tracking
|
|
2
|
+
|
|
3
|
+
**Branch**: `021-review-iterations` | **Date**: 2026-03-21 | **Spec**: [spec.md](./spec.md)
|
|
4
|
+
**Input**: Feature specification from `/specs/021-review-iterations/spec.md`
|
|
5
|
+
|
|
6
|
+
## Summary
|
|
7
|
+
|
|
8
|
+
Activer le champ `reviewIterations` dans `FeatureState` en incrementant automatiquement le compteur dans `advance_step()` lorsque l'etape completee est une gate de review. Ajout d'une constante `REVIEW_GATES` pour centraliser l'identification des gates.
|
|
9
|
+
|
|
10
|
+
## Technical Context
|
|
11
|
+
|
|
12
|
+
**Language/Version**: Python 3.11+
|
|
13
|
+
**Primary Dependencies**: typer (>=0.12), rich (>=13) — aucune nouvelle dependance
|
|
14
|
+
**Storage**: Fichiers locaux (state.json)
|
|
15
|
+
**Testing**: pytest (>=8) avec fixtures temporaires
|
|
16
|
+
**Target Platform**: CLI multi-OS (macOS, Linux, Windows)
|
|
17
|
+
**Project Type**: CLI
|
|
18
|
+
**Performance Goals**: N/A — modification d'un compteur en memoire
|
|
19
|
+
**Constraints**: Retrocompatibilite totale avec les state.json existants
|
|
20
|
+
**Scale/Scope**: 3 fichiers modifies, ~15 lignes de code, ~30 lignes de tests
|
|
21
|
+
|
|
22
|
+
## Constitution Check
|
|
23
|
+
|
|
24
|
+
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
|
25
|
+
|
|
26
|
+
| Principe | Verdict | Justification |
|
|
27
|
+
|----------|---------|---------------|
|
|
28
|
+
| I. Spec-Driven Development | PASS | Spec redigee et validee avant tout code |
|
|
29
|
+
| II. Pipeline Sequentiel | PASS | Le champ `reviewIterations` est deja dans le pipeline — on corrige son non-fonctionnement |
|
|
30
|
+
| III. Gates de Review | PASS | Cette feature IMPLEMENTE le tracking exige par ce principe ("Le nombre d'iterations de review DOIT etre trace dans reviewIterations") |
|
|
31
|
+
| IV. Retrocompatibilite | PASS | Les state.json existants avec `reviewIterations: {}` ou absent restent valides (FR-005) |
|
|
32
|
+
| V. Simplicite (YAGNI) | PASS | Modification minimale : 1 constante + 2 lignes dans `advance_step()`. Pas d'abstraction nouvelle |
|
|
33
|
+
| VI. Testabilite | PASS | Tests unitaires ajoutes pour chaque FR |
|
|
34
|
+
| VII. Integration Linear | PASS | Aucun impact sur le mapping Linear |
|
|
35
|
+
|
|
36
|
+
## Project Structure
|
|
37
|
+
|
|
38
|
+
### Documentation (this feature)
|
|
39
|
+
|
|
40
|
+
```text
|
|
41
|
+
specs/021-review-iterations/
|
|
42
|
+
├── spec.md
|
|
43
|
+
├── plan.md # This file
|
|
44
|
+
├── research.md # Phase 0 output
|
|
45
|
+
├── checklists/
|
|
46
|
+
│ └── requirements.md
|
|
47
|
+
└── tasks.md # Phase 2 output (via /speckit.tasks)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Source Code (repository root)
|
|
51
|
+
|
|
52
|
+
```text
|
|
53
|
+
src/devflow_cli/
|
|
54
|
+
├── __init__.py # + REVIEW_GATES constant (FR-002)
|
|
55
|
+
└── core/
|
|
56
|
+
└── state.py # advance_step() modification (FR-001, FR-003)
|
|
57
|
+
|
|
58
|
+
tests/
|
|
59
|
+
└── test_state.py # + tests incrementation review iterations
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Structure Decision**: Modification in-place de fichiers existants. Aucun nouveau fichier source. Structure identique au projet actuel.
|
|
63
|
+
|
|
64
|
+
## Complexity Tracking
|
|
65
|
+
|
|
66
|
+
Aucune violation de constitution. Pas de complexite ajoutee a justifier.
|
|
67
|
+
|
|
68
|
+
## Design
|
|
69
|
+
|
|
70
|
+
### Approche
|
|
71
|
+
|
|
72
|
+
L'incrementation se fait dans `advance_step()` (state.py), juste apres l'enregistrement du timestamp (ligne 206), car c'est le point unique ou une etape est marquee comme completee. C'est coherent avec le pattern existant : `advance_step()` gere deja `completedSteps` et `stepTimestamps`.
|
|
73
|
+
|
|
74
|
+
### Constante REVIEW_GATES
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
# Dans __init__.py, apres OPTIONAL_STEPS
|
|
78
|
+
REVIEW_GATES = {"review-spec", "review-tasks", "review-impl"}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Type `set` (comme `OPTIONAL_STEPS`) car l'ordre n'importe pas — on teste uniquement l'appartenance.
|
|
82
|
+
|
|
83
|
+
### Modification advance_step()
|
|
84
|
+
|
|
85
|
+
Apres la ligne 206 (mise a jour du timestamp), ajouter :
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
# Incrementer reviewIterations pour les gates de review
|
|
89
|
+
if completed_step in REVIEW_GATES:
|
|
90
|
+
state.reviewIterations[completed_step] = state.reviewIterations.get(completed_step, 0) + 1
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Utilisation de `.get(key, 0)` pour gerer :
|
|
94
|
+
- Premier passage : cle absente → 0 + 1 = 1
|
|
95
|
+
- Passages suivants (apres rollback) : valeur existante + 1
|
|
96
|
+
- State.json legacy avec `reviewIterations: {}` : fonctionne identiquement
|
|
97
|
+
|
|
98
|
+
### Ce qui ne change PAS
|
|
99
|
+
|
|
100
|
+
- `rollback_step()` : ne touche pas `reviewIterations` (compteur cumulatif = historique)
|
|
101
|
+
- `create_state()` : `reviewIterations` reste `{}` par default (premier passage l'initialisera)
|
|
102
|
+
- `convert_speckit_state()` : continue d'injecter `{gate: 0}` pour les gates auto-validees
|
|
103
|
+
- `_validate_state()` : pas de nettoyage de `reviewIterations` (les cles inconnues sont inoffensives)
|
|
104
|
+
- Commandes Claude Code (`review-*.md`) : l'instruction "Incrementer reviewIterations" reste — le LLM ecrit dans state.json, puis `advance_step()` incremente aussi. Double source = pas de probleme car le LLM appelle `advance_step()` via la CLI pour avancer, et c'est la que l'incrementation fiable se fait.
|
|
105
|
+
|
|
106
|
+
### Tests prevus
|
|
107
|
+
|
|
108
|
+
1. **test_advance_step_increments_review_iterations** : Avancer `review-spec` → `reviewIterations["review-spec"]` == 1
|
|
109
|
+
2. **test_advance_step_no_increment_for_non_review** : Avancer `spec` → `reviewIterations` inchange
|
|
110
|
+
3. **test_advance_step_cumulative_review_iterations** : Avancer review-spec, rollback, re-avancer → compteur == 2
|
|
111
|
+
4. **test_advance_step_increments_each_gate_independently** : Avancer review-spec puis review-tasks → chaque gate a son propre compteur
|
|
112
|
+
5. **test_review_gates_constant** : `REVIEW_GATES` est sous-ensemble de `STEPS` et contient exactement 3 elements
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Research: Review Iterations Tracking
|
|
2
|
+
|
|
3
|
+
**Branch**: `021-review-iterations` | **Date**: 2026-03-21
|
|
4
|
+
|
|
5
|
+
## Point d'insertion dans advance_step()
|
|
6
|
+
|
|
7
|
+
**Decision**: Incrementer `reviewIterations` juste apres la mise a jour de `stepTimestamps` (ligne 206), avant le calcul de la prochaine etape.
|
|
8
|
+
|
|
9
|
+
**Rationale**: Le pattern existant dans `advance_step()` est sequentiel :
|
|
10
|
+
1. Verifier la legalite de la transition (lignes 171-195)
|
|
11
|
+
2. Ajouter a `completedSteps` (ligne 198-199)
|
|
12
|
+
3. Enregistrer `stepTimestamps` (lignes 202-206)
|
|
13
|
+
4. **→ Nouveau : incrementer `reviewIterations`**
|
|
14
|
+
5. Calculer la prochaine etape (lignes 208-220)
|
|
15
|
+
|
|
16
|
+
Inserer entre 3 et 5 preserve la logique : d'abord enregistrer l'historique (timestamps + iterations), puis avancer.
|
|
17
|
+
|
|
18
|
+
**Alternatives considered**:
|
|
19
|
+
- `validate_and_advance()` : trop haut niveau, creerait un couplage validation ↔ compteur
|
|
20
|
+
- Fonction separee `record_review_iteration()` : sur-ingenierie pour 2 lignes de code
|
|
21
|
+
- Dans `write_state()` : wrong layer — `write_state()` est I/O, pas logique metier
|
|
22
|
+
|
|
23
|
+
## Type de la constante REVIEW_GATES
|
|
24
|
+
|
|
25
|
+
**Decision**: `set[str]` (frozenset rejete).
|
|
26
|
+
|
|
27
|
+
**Rationale**: `OPTIONAL_STEPS` est deja un `set` dans `__init__.py`. Utiliser le meme type pour la coherence. `frozenset` serait plus "correct" (immutable) mais `OPTIONAL_STEPS` n'est pas frozenset, donc on suit le pattern existant (Constitution V : "Les patterns existants DOIVENT etre suivis").
|
|
28
|
+
|
|
29
|
+
**Alternatives considered**:
|
|
30
|
+
- `frozenset` : plus safe mais inconsistant avec `OPTIONAL_STEPS`
|
|
31
|
+
- `list` : O(n) lookup vs O(1) pour set — inutilement lent
|
|
32
|
+
- `tuple` : meme probleme que list
|
|
33
|
+
|
|
34
|
+
## Double incrementation (CLI + LLM)
|
|
35
|
+
|
|
36
|
+
**Decision**: Pas de probleme. Les commandes Claude Code (`review-*.md`) disent au LLM d'incrementer `reviewIterations` via ecriture directe dans state.json. Mais ensuite, le LLM appelle `advance_step()` (via la commande devflow) pour avancer l'etape, et c'est la que l'incrementation fiable se fait.
|
|
37
|
+
|
|
38
|
+
**Rationale**: Deux scenarios :
|
|
39
|
+
1. Le LLM incremente PUIS advance_step incremente → double comptage ? Non : le LLM ecrit dans state.json, mais advance_step travaille sur l'objet FeatureState en memoire (charge avant l'incrementation LLM), donc l'incrementation CLI ecrase celle du LLM via write_state. Resultat net = 1 incrementation.
|
|
40
|
+
2. Le LLM n'incremente PAS (oubli, bug) → advance_step incremente quand meme. Le compteur reste fiable.
|
|
41
|
+
|
|
42
|
+
Conclusion : l'incrementation dans `advance_step()` est la source de verite. L'instruction dans les commandes Claude Code est redondante mais inoffensive.
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# Feature Specification: Review Iterations Tracking
|
|
2
|
+
|
|
3
|
+
**Feature Branch**: `021-review-iterations`
|
|
4
|
+
**Created**: 2026-03-21
|
|
5
|
+
**Status**: Draft
|
|
6
|
+
**Project Type**: Brownfield
|
|
7
|
+
**Input**: reviewIterations : code mort — Le champ existe dans FeatureState, il est initialise a {}, mais jamais incremente nulle part.
|
|
8
|
+
|
|
9
|
+
## Comportement existant *(mandatory for brownfield)*
|
|
10
|
+
|
|
11
|
+
### Etat actuel
|
|
12
|
+
|
|
13
|
+
Le champ `reviewIterations` est declare dans le dataclass `FeatureState` (`state.py:19`) avec un type `dict[str, int]` et un default `{}`. Il est :
|
|
14
|
+
|
|
15
|
+
1. **Cree vide** par `create_state()` (implicitement via le default du dataclass)
|
|
16
|
+
2. **Peuple avec des `0`** uniquement par `convert_speckit_state()` pour les gates auto-validees lors de la migration speckit (lignes 304-317)
|
|
17
|
+
3. **Serialise/deserialise** correctement via `to_dict()` et `read_state()`
|
|
18
|
+
4. **Jamais incremente** par aucune fonction Python du projet
|
|
19
|
+
|
|
20
|
+
Les commandes Claude Code (`review-spec.md:29`, `review-tasks.md:32`, `review-impl.md:31`) documentent explicitement : "Incrementer `reviewIterations.review-spec` (+1 a chaque execution, PASS ou BLOQUANT)". Mais cette instruction s'adresse au LLM qui execute la commande — elle n'est jamais validee ni appliquee par le code CLI.
|
|
21
|
+
|
|
22
|
+
Le resultat : un champ toujours vide `{}` dans les state.json de features creees normalement, ce qui rend `devflow metrics` incapable de reporter les iterations de review.
|
|
23
|
+
|
|
24
|
+
### Flux existants
|
|
25
|
+
|
|
26
|
+
1. **Creation feature** : `devflow feature KS-123` → `create_state()` → `reviewIterations: {}`
|
|
27
|
+
2. **Progression pipeline** : `advance_step()` ne touche jamais `reviewIterations`
|
|
28
|
+
3. **Rollback** : `rollback_step()` ne touche jamais `reviewIterations`
|
|
29
|
+
4. **Migration speckit** : `convert_speckit_state()` injecte `{gate: 0}` pour les gates auto-validees
|
|
30
|
+
5. **Commandes review Claude Code** : le LLM est cense incrementer le compteur via ecriture directe dans state.json — non valide par la CLI
|
|
31
|
+
|
|
32
|
+
### Dependances identifiees
|
|
33
|
+
|
|
34
|
+
- **`FeatureState` (state.py:14-23)** : Le dataclass porte le champ. Toute modification impacte serialisation/deserialisation.
|
|
35
|
+
- **`advance_step()` (state.py:152-222)** : Point d'entree naturel pour l'incrementation — gere deja `stepTimestamps` et `completedSteps`.
|
|
36
|
+
- **`validate_and_advance()` (state.py:333-366)** : Compose validation + avancement. Point d'entree alternatif.
|
|
37
|
+
- **Commandes review (`commands/devflow.review-*.md`)** : Documentent l'incrementation cote LLM. Doivent rester coherentes avec le code CLI.
|
|
38
|
+
- **`devflow metrics` (`commands/devflow.metrics.md:19`)** : Consomme `reviewIterations` pour le reporting. Beneficiaire direct.
|
|
39
|
+
- **Constitution (Principe III, lignes 59-60)** : "Le nombre d'iterations de review DOIT etre trace dans `reviewIterations`." — obligation constitutionnelle.
|
|
40
|
+
|
|
41
|
+
### Limitations connues
|
|
42
|
+
|
|
43
|
+
- Le champ est toujours `{}` pour les features normales (non-migrees depuis speckit)
|
|
44
|
+
- `devflow metrics` ne peut pas reporter le nombre d'iterations de review
|
|
45
|
+
- Aucune validation que le LLM a reellement incremente le compteur
|
|
46
|
+
- Pas de distinction entre PASS et BLOQUANT dans le compteur (juste un entier)
|
|
47
|
+
|
|
48
|
+
## Impact sur l'existant *(mandatory for brownfield)*
|
|
49
|
+
|
|
50
|
+
### Composants affectes
|
|
51
|
+
|
|
52
|
+
- **`state.py` — `advance_step()`** : Modifie pour incrementer `reviewIterations` quand l'etape completee est une gate de review
|
|
53
|
+
- **`state.py` — `rollback_step()`** : Inchange — les iterations de review sont un historique, pas un etat reversible
|
|
54
|
+
- **`__init__.py`** : Ajout d'une constante `REVIEW_GATES` pour identifier les etapes de review (eviter le hardcoding)
|
|
55
|
+
- **Tests (`test_state.py`)** : Ajout de tests pour l'incrementation
|
|
56
|
+
|
|
57
|
+
### Risques de regression
|
|
58
|
+
|
|
59
|
+
- **Serialisation state.json** : Aucun risque — le champ existe deja, seul son contenu change (de `{}` a `{"review-spec": 1}` etc.)
|
|
60
|
+
- **Migration speckit** : Aucun risque — `convert_speckit_state()` ecrit deja des valeurs dans `reviewIterations`
|
|
61
|
+
- **Retrocompatibilite** : Les state.json existants avec `reviewIterations: {}` restent valides — le compteur demarre simplement a 0 implicitement
|
|
62
|
+
|
|
63
|
+
### Strategie de migration
|
|
64
|
+
|
|
65
|
+
Aucune migration necessaire. Les state.json existants restent valides. Les features deja en cours continueront normalement — leurs compteurs demarreront a 0 implicitement (absence de cle = 0 iterations passees). Retrocompatibilite totale.
|
|
66
|
+
|
|
67
|
+
## User Scenarios & Testing *(mandatory)*
|
|
68
|
+
|
|
69
|
+
### User Story 1 - Tracking automatique des iterations de review (Priority: P1)
|
|
70
|
+
|
|
71
|
+
Quand une gate de review est completee (PASS), le systeme incremente automatiquement le compteur d'iterations correspondant dans state.json. L'utilisateur n'a rien a faire — c'est transparent.
|
|
72
|
+
|
|
73
|
+
**Changement vs existant** : Aujourd'hui, `advance_step("review-spec")` met a jour `completedSteps` et `stepTimestamps` mais ignore `reviewIterations`. Demain, il incremente aussi le compteur.
|
|
74
|
+
|
|
75
|
+
**Why this priority** : C'est le coeur de la feature. Sans ca, le champ reste mort.
|
|
76
|
+
|
|
77
|
+
**Independent Test** : Creer un state a l'etape `review-spec`, appeler `advance_step("review-spec")`, verifier que `reviewIterations["review-spec"]` vaut 1.
|
|
78
|
+
|
|
79
|
+
**Acceptance Scenarios**:
|
|
80
|
+
|
|
81
|
+
1. **Given** un state avec `currentStep: "review-spec"` et `reviewIterations: {}`, **When** `advance_step(state, "review-spec")` est appele, **Then** `state.reviewIterations["review-spec"]` vaut 1 et `currentStep` avance a l'etape suivante.
|
|
82
|
+
2. **Given** un state avec `currentStep: "review-tasks"` et `reviewIterations: {"review-spec": 2}`, **When** `advance_step(state, "review-tasks")` est appele, **Then** `state.reviewIterations` contient `{"review-spec": 2, "review-tasks": 1}`.
|
|
83
|
+
3. **Given** un state avec `currentStep: "spec"` (pas une gate), **When** `advance_step(state, "spec")` est appele, **Then** `reviewIterations` est inchange.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
### User Story 2 - Compteur persistant apres rollback + re-review (Priority: P1)
|
|
88
|
+
|
|
89
|
+
Quand un utilisateur fait un rollback depuis une etape post-review, puis repasse la review, le compteur s'incremente a nouveau (compteur cumulatif, pas remis a zero).
|
|
90
|
+
|
|
91
|
+
**Why this priority** : C'est le scenario typique d'une review BLOQUANT → correction → re-review. Le compteur doit refleter le nombre reel de passages.
|
|
92
|
+
|
|
93
|
+
**Independent Test** : Avancer review-spec (iterations=1), rollback vers review-spec, re-avancer (iterations=2).
|
|
94
|
+
|
|
95
|
+
**Acceptance Scenarios**:
|
|
96
|
+
|
|
97
|
+
1. **Given** un state ou `review-spec` a ete avance une fois (`reviewIterations: {"review-spec": 1}`), puis rollback a ete effectue (currentStep revient a "review-spec"), **When** `advance_step(state, "review-spec")` est appele a nouveau, **Then** `reviewIterations["review-spec"]` vaut 2.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
### User Story 3 - Constante REVIEW_GATES centralisee (Priority: P2)
|
|
102
|
+
|
|
103
|
+
Les gates de review sont identifiees par une constante `REVIEW_GATES` dans `__init__.py`, pas par du hardcoding dans `advance_step()`.
|
|
104
|
+
|
|
105
|
+
**Why this priority** : Evite la duplication et le risque d'oublier une gate si le pipeline evolue.
|
|
106
|
+
|
|
107
|
+
**Independent Test** : Verifier que `REVIEW_GATES` est un sous-ensemble de `STEPS` et contient exactement les etapes `review-*`.
|
|
108
|
+
|
|
109
|
+
**Acceptance Scenarios**:
|
|
110
|
+
|
|
111
|
+
1. **Given** la constante `REVIEW_GATES`, **When** on verifie son contenu, **Then** elle contient exactement `{"review-spec", "review-tasks", "review-impl"}` et chaque element est dans `STEPS`.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
### Edge Cases
|
|
116
|
+
|
|
117
|
+
- Que se passe-t-il si `reviewIterations` contient une cle qui n'est pas dans `REVIEW_GATES` (ex: cle residuelle d'une migration) ? Le systeme l'ignore — seules les cles correspondant a des gates connues sont incrementees.
|
|
118
|
+
- Que se passe-t-il pour un state.json legacy sans `reviewIterations` ? Le default `{}` s'applique via le dataclass — premiere incrementation cree la cle a 1. Retrocompatibilite preservee.
|
|
119
|
+
- Que se passe-t-il si `advance_step()` est appele sur une etape non-review ? `reviewIterations` n'est pas touche.
|
|
120
|
+
|
|
121
|
+
## Requirements *(mandatory)*
|
|
122
|
+
|
|
123
|
+
### Functional Requirements
|
|
124
|
+
|
|
125
|
+
- **FR-001** : Le systeme DOIT incrementer `reviewIterations[step]` de 1 chaque fois que `advance_step()` complete une etape qui est une gate de review.
|
|
126
|
+
- **FR-002** : Le systeme DOIT fournir une constante `REVIEW_GATES` dans `__init__.py` listant les etapes de review (`review-spec`, `review-tasks`, `review-impl`).
|
|
127
|
+
- **FR-003** : Le systeme NE DOIT PAS modifier `reviewIterations` lors de l'avancement d'une etape non-review.
|
|
128
|
+
- **FR-004** : Le systeme DOIT preserver les valeurs existantes de `reviewIterations` lors d'un rollback (pas de remise a zero).
|
|
129
|
+
- **FR-005** : Le systeme DOIT rester retrocompatible avec les state.json existants ou `reviewIterations` est `{}` ou absent.
|
|
130
|
+
|
|
131
|
+
### Key Entities
|
|
132
|
+
|
|
133
|
+
- **REVIEW_GATES** : Ensemble des etapes de review dans le pipeline. Utilise par `advance_step()` pour determiner si l'incrementation est necessaire.
|
|
134
|
+
- **reviewIterations** : Dictionnaire `{gate_name: count}` dans `FeatureState`. Compteur cumulatif (jamais remis a zero) du nombre de fois qu'une gate de review a ete traversee.
|
|
135
|
+
|
|
136
|
+
## Success Criteria *(mandatory)*
|
|
137
|
+
|
|
138
|
+
### Measurable Outcomes
|
|
139
|
+
|
|
140
|
+
- **SC-001** : Apres chaque passage d'une gate de review, le compteur correspondant dans state.json est incremente de 1.
|
|
141
|
+
- **SC-002** : Une feature qui passe 3 fois par review-spec (2 BLOQUANT + 1 PASS) affiche `reviewIterations: {"review-spec": 3}` dans son state.json.
|
|
142
|
+
- **SC-003** : No regression — les state.json existants (avec `reviewIterations: {}` ou sans le champ) restent lisibles et valides. Les 244 tests existants continuent de passer.
|
|
143
|
+
- **SC-004** : `devflow metrics` peut reporter le nombre d'iterations de review pour chaque feature a partir des donnees dans state.json.
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# Tasks: Review Iterations Tracking
|
|
2
|
+
|
|
3
|
+
**Input**: Design documents from `/specs/021-review-iterations/`
|
|
4
|
+
**Prerequisites**: plan.md (required), spec.md (required), research.md
|
|
5
|
+
|
|
6
|
+
**Tests**: Tests inclus — la constitution exige que tout nouveau comportement CLI soit accompagne d'un test (Principe VI).
|
|
7
|
+
|
|
8
|
+
**Organization**: Tasks groupees par user story. US1 et US2 sont P1, US3 est P2.
|
|
9
|
+
|
|
10
|
+
## Format: `[ID] [P?] [Story] Description`
|
|
11
|
+
|
|
12
|
+
- **[P]**: Can run in parallel (different files, no dependencies)
|
|
13
|
+
- **[Story]**: Which user story this task belongs to (e.g., US1, US2, US3)
|
|
14
|
+
- Include exact file paths in descriptions
|
|
15
|
+
|
|
16
|
+
## Phase 1: Setup
|
|
17
|
+
|
|
18
|
+
**Purpose**: Ajout de la constante REVIEW_GATES
|
|
19
|
+
|
|
20
|
+
- [x] [T-001] [P] Add REVIEW_GATES constant in src/devflow_cli/__init__.py — set {"review-spec", "review-tasks", "review-impl"} after OPTIONAL_STEPS (line 21) — Ref: FR-002
|
|
21
|
+
|
|
22
|
+
**Checkpoint**: La constante est importable. Verifier avec `from devflow_cli import REVIEW_GATES`.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Phase 2: User Story 1 - Tracking automatique des iterations de review (Priority: P1)
|
|
27
|
+
|
|
28
|
+
**Goal**: `advance_step()` incremente automatiquement `reviewIterations[step]` quand l'etape completee est une gate de review.
|
|
29
|
+
|
|
30
|
+
**Independent Test**: Creer un state a l'etape `review-spec`, appeler `advance_step("review-spec")`, verifier que `reviewIterations["review-spec"]` vaut 1.
|
|
31
|
+
|
|
32
|
+
### Tests for User Story 1
|
|
33
|
+
|
|
34
|
+
- [x] [T-002] [P] [P1] [US1] Add test_advance_step_increments_review_iterations in tests/test_state.py — Given state at review-spec with reviewIterations {}, When advance_step(state, "review-spec"), Then reviewIterations["review-spec"] == 1 — Ref: FR-001
|
|
35
|
+
- [x] [T-003] [P] [P1] [US1] Add test_advance_step_no_increment_for_non_review in tests/test_state.py — Given state at spec, When advance_step(state, "spec"), Then reviewIterations unchanged (still {}) — Ref: FR-003
|
|
36
|
+
- [x] [T-004] [P] [P1] [US1] Add test_advance_step_increments_each_gate_independently in tests/test_state.py — Advance review-spec then advance to review-tasks, verify each gate has its own counter {"review-spec": 1, "review-tasks": 1} — Ref: FR-001
|
|
37
|
+
|
|
38
|
+
### Implementation for User Story 1
|
|
39
|
+
|
|
40
|
+
- [x] [T-005] [P1] [US1] Import REVIEW_GATES in src/devflow_cli/core/state.py (add to existing import from devflow_cli line 10) and add review iteration increment in advance_step() after stepTimestamps update (after line 206): `if completed_step in REVIEW_GATES: state.reviewIterations[completed_step] = state.reviewIterations.get(completed_step, 0) + 1` — Ref: FR-001, FR-003
|
|
41
|
+
|
|
42
|
+
**Checkpoint**: Les 3 tests passent. `advance_step()` incremente pour les gates, ignore pour les autres etapes.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Phase 3: User Story 2 - Compteur persistant apres rollback + re-review (Priority: P1)
|
|
47
|
+
|
|
48
|
+
**Goal**: Le compteur est cumulatif — apres rollback et re-review, il s'incremente a nouveau sans remise a zero.
|
|
49
|
+
|
|
50
|
+
**Independent Test**: Avancer review-spec (iterations=1), rollback, re-avancer (iterations=2).
|
|
51
|
+
|
|
52
|
+
### Tests for User Story 2
|
|
53
|
+
|
|
54
|
+
- [x] [T-006] [P1] [US2] Add test_advance_step_cumulative_review_iterations in tests/test_state.py — advance review-spec (count=1), rollback_step to review-spec, advance review-spec again (count=2). Verify reviewIterations["review-spec"] == 2 — Ref: FR-004
|
|
55
|
+
|
|
56
|
+
### Implementation for User Story 2
|
|
57
|
+
|
|
58
|
+
Aucune implementation supplementaire — le comportement cumulatif decoule naturellement de l'implementation US1 (`.get(key, 0) + 1` incremente la valeur existante) et du fait que `rollback_step()` ne touche pas `reviewIterations`. Le test T006 valide ce comportement.
|
|
59
|
+
|
|
60
|
+
**Checkpoint**: T006 passe. Le compteur survit au rollback.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Phase 4: User Story 3 - Constante REVIEW_GATES centralisee (Priority: P2)
|
|
65
|
+
|
|
66
|
+
**Goal**: Les gates de review sont identifiees par une constante, pas du hardcoding.
|
|
67
|
+
|
|
68
|
+
**Independent Test**: Verifier que REVIEW_GATES est un sous-ensemble de STEPS et contient exactement 3 elements.
|
|
69
|
+
|
|
70
|
+
### Tests for User Story 3
|
|
71
|
+
|
|
72
|
+
- [x] [T-007] [P] [P2] [US3] Add test_review_gates_subset_of_steps in tests/test_state.py — assert REVIEW_GATES is subset of set(STEPS), assert len(REVIEW_GATES) == 3, assert all elements start with "review-" — Ref: FR-002
|
|
73
|
+
|
|
74
|
+
### Implementation for User Story 3
|
|
75
|
+
|
|
76
|
+
Deja implementee par T001. Le test T007 valide la constante.
|
|
77
|
+
|
|
78
|
+
**Checkpoint**: T007 passe. La constante est coherente avec STEPS.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Phase 5: Polish & Cross-Cutting Concerns
|
|
83
|
+
|
|
84
|
+
**Purpose**: Validation retrocompatibilite et tests existants
|
|
85
|
+
|
|
86
|
+
- [x] [T-008] [P] Add test_advance_step_review_iterations_legacy_state in tests/test_state.py — Given state loaded from JSON without reviewIterations key (simulating legacy), When advance_step on review-spec, Then reviewIterations["review-spec"] == 1 — Ref: FR-005
|
|
87
|
+
- [x] [T-009] Run full test suite (pytest tests/ -v) — verify all 244+ existing tests still pass, no regression — Ref: SC-003
|
|
88
|
+
|
|
89
|
+
**Checkpoint**: Suite de tests complete. Zero regression.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Dependencies & Execution Order
|
|
94
|
+
|
|
95
|
+
### Phase Dependencies
|
|
96
|
+
|
|
97
|
+
- **Phase 1 (Setup)**: Aucune dependance — constante standalone
|
|
98
|
+
- **Phase 2 (US1)**: Depend de Phase 1 ([T-005] importe REVIEW_GATES cree par [T-001])
|
|
99
|
+
- **Phase 3 (US2)**: Depend de Phase 2 ([T-006] utilise advance_step modifie par [T-005])
|
|
100
|
+
- **Phase 4 (US3)**: Depend de Phase 1 seulement ([T-007] teste la constante [T-001])
|
|
101
|
+
- **Phase 5 (Polish)**: Depend de Phase 2 (tests de retrocompatibilite)
|
|
102
|
+
|
|
103
|
+
### User Story Dependencies
|
|
104
|
+
|
|
105
|
+
- **US1 (P1)**: Depend de [T-001] (constante). Coeur de la feature.
|
|
106
|
+
- **US2 (P1)**: Depend de US1 (comportement). Aucun code supplementaire.
|
|
107
|
+
- **US3 (P2)**: Depend de [T-001] seulement. Peut etre teste en parallele avec US1.
|
|
108
|
+
|
|
109
|
+
### Parallel Opportunities
|
|
110
|
+
|
|
111
|
+
- [T-001] et [T-007] peuvent etre implementes en parallele (fichiers differents, pas de dependance)
|
|
112
|
+
- [T-002], [T-003], [T-004] peuvent etre **ecrits** en parallele, mais ne passeront qu'apres [T-005] (ils testent le code de T-005)
|
|
113
|
+
- [T-008] peut demarrer des que [T-005] est complete
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Implementation Strategy
|
|
118
|
+
|
|
119
|
+
### MVP First (US1 Only)
|
|
120
|
+
|
|
121
|
+
1. [T-001]: Constante REVIEW_GATES
|
|
122
|
+
2. [T-005]: Modification advance_step()
|
|
123
|
+
3. [T-002]+[T-003]+[T-004]: Tests US1
|
|
124
|
+
4. **STOP and VALIDATE**: `pytest tests/test_state.py -v -k "review_iterations"`
|
|
125
|
+
|
|
126
|
+
### Incremental Delivery
|
|
127
|
+
|
|
128
|
+
1. [T-001] → [T-005] → [T-002]/[T-003]/[T-004] → US1 fonctionnel
|
|
129
|
+
2. [T-006] → US2 valide (zero code supplementaire)
|
|
130
|
+
3. [T-007] → US3 valide (zero code supplementaire)
|
|
131
|
+
4. [T-008] → [T-009] → Retrocompatibilite confirmee
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Notes
|
|
136
|
+
|
|
137
|
+
- 9 taches au total, dont 1 seule tache d'implementation reelle ([T-005])
|
|
138
|
+
- La feature est minimaliste par design : 2 lignes de code + 1 constante
|
|
139
|
+
- US2 et US3 ne necessitent pas de code supplementaire — juste des tests validant le comportement emergent
|
|
140
|
+
- Commit recommande apres [T-005] (implementation) puis apres [T-009] (validation complete)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Specification Quality Checklist: Fix Regen Command
|
|
2
|
+
|
|
3
|
+
**Purpose**: Validate specification completeness and quality before proceeding to planning
|
|
4
|
+
**Created**: 2026-03-21
|
|
5
|
+
**Feature**: [spec.md](../spec.md)
|
|
6
|
+
|
|
7
|
+
## Content Quality
|
|
8
|
+
|
|
9
|
+
- [x] No implementation details (languages, frameworks, APIs)
|
|
10
|
+
- [x] Focused on user value and business needs
|
|
11
|
+
- [x] Written for non-technical stakeholders
|
|
12
|
+
- [x] All mandatory sections completed
|
|
13
|
+
|
|
14
|
+
## Requirement Completeness
|
|
15
|
+
|
|
16
|
+
- [x] No [NEEDS CLARIFICATION] markers remain
|
|
17
|
+
- [x] Requirements are testable and unambiguous
|
|
18
|
+
- [x] Success criteria are measurable
|
|
19
|
+
- [x] Success criteria are technology-agnostic (no implementation details)
|
|
20
|
+
- [x] All acceptance scenarios are defined
|
|
21
|
+
- [x] Edge cases are identified
|
|
22
|
+
- [x] Scope is clearly bounded
|
|
23
|
+
- [x] Dependencies and assumptions identified
|
|
24
|
+
|
|
25
|
+
## Feature Readiness
|
|
26
|
+
|
|
27
|
+
- [x] All functional requirements have clear acceptance criteria
|
|
28
|
+
- [x] User scenarios cover primary flows
|
|
29
|
+
- [x] Feature meets measurable outcomes defined in Success Criteria
|
|
30
|
+
- [x] No implementation details leak into specification
|
|
31
|
+
|
|
32
|
+
## Notes
|
|
33
|
+
|
|
34
|
+
- Spec references file paths in "Comportement existant" — acceptable for brownfield documentation.
|
|
35
|
+
- No NEEDS CLARIFICATION — scope is narrow (rename + update references).
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Implementation Plan: Fix Regen Command
|
|
2
|
+
|
|
3
|
+
**Branch**: `022-fix-regen-command` | **Date**: 2026-03-21 | **Spec**: [spec.md](./spec.md)
|
|
4
|
+
**Input**: Feature specification from `/specs/022-fix-regen-command/spec.md`
|
|
5
|
+
|
|
6
|
+
## Summary
|
|
7
|
+
|
|
8
|
+
Renommer la commande CLI `devflow regen` en `devflow stale` pour aligner le nom avec le comportement reel (detection de desynchronisation, pas de regeneration). Mettre a jour toutes les references : commande Claude Code, tests, documentation.
|
|
9
|
+
|
|
10
|
+
## Technical Context
|
|
11
|
+
|
|
12
|
+
**Language/Version**: Python 3.11+
|
|
13
|
+
**Primary Dependencies**: typer (>=0.12), rich (>=13) — aucune nouvelle dependance
|
|
14
|
+
**Storage**: N/A — renommage pur
|
|
15
|
+
**Testing**: pytest (>=8)
|
|
16
|
+
**Target Platform**: CLI multi-OS
|
|
17
|
+
**Project Type**: CLI
|
|
18
|
+
**Performance Goals**: N/A
|
|
19
|
+
**Constraints**: Pas d'alias de retrocompatibilite
|
|
20
|
+
**Scale/Scope**: 6 fichiers renommes/modifies, 0 nouvelles lignes de logique
|
|
21
|
+
|
|
22
|
+
## Constitution Check
|
|
23
|
+
|
|
24
|
+
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
|
25
|
+
|
|
26
|
+
| Principe | Verdict | Justification |
|
|
27
|
+
|----------|---------|---------------|
|
|
28
|
+
| I. Spec-Driven Development | PASS | Spec redigee avant code |
|
|
29
|
+
| II. Pipeline Sequentiel | PASS | Aucun impact sur le pipeline |
|
|
30
|
+
| III. Gates de Review | PASS | Aucun impact |
|
|
31
|
+
| IV. Retrocompatibilite | PASS | Pas d'alias — le nom `regen` n'a jamais fait ce qu'il promettait, pas de contrat a preserver |
|
|
32
|
+
| V. Simplicite (YAGNI) | PASS | Renommage pur, zero complexite ajoutee |
|
|
33
|
+
| VI. Testabilite | PASS | Tests renommes et mis a jour |
|
|
34
|
+
| VII. Integration Linear | PASS | Aucun impact |
|
|
35
|
+
|
|
36
|
+
## Project Structure
|
|
37
|
+
|
|
38
|
+
### Documentation (this feature)
|
|
39
|
+
|
|
40
|
+
```text
|
|
41
|
+
specs/022-fix-regen-command/
|
|
42
|
+
├── spec.md
|
|
43
|
+
├── plan.md # This file
|
|
44
|
+
├── research.md # Phase 0 output
|
|
45
|
+
└── checklists/
|
|
46
|
+
└── requirements.md
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Source Code (repository root)
|
|
50
|
+
|
|
51
|
+
```text
|
|
52
|
+
src/devflow_cli/
|
|
53
|
+
├── cli.py # Renommage enregistrement regen → stale
|
|
54
|
+
└── commands/
|
|
55
|
+
├── regen.py # SUPPRIME
|
|
56
|
+
└── stale.py # CREE (contenu identique, messages reformules)
|
|
57
|
+
|
|
58
|
+
commands/
|
|
59
|
+
└── devflow.regen.md # Modifie (appel devflow stale --json)
|
|
60
|
+
|
|
61
|
+
tests/
|
|
62
|
+
├── test_cmd_regen.py # SUPPRIME
|
|
63
|
+
└── test_cmd_stale.py # CREE (contenu identique, references mises a jour)
|
|
64
|
+
|
|
65
|
+
docs/
|
|
66
|
+
├── cli-reference.md # Section renommee
|
|
67
|
+
└── commands-reference.md # Reference mise a jour
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Structure Decision**: Renommage de fichiers (suppression ancien + creation nouveau). Pas de refactoring de la logique interne.
|
|
71
|
+
|
|
72
|
+
## Complexity Tracking
|
|
73
|
+
|
|
74
|
+
Aucune violation de constitution. Pas de complexite ajoutee.
|
|
75
|
+
|
|
76
|
+
## Design
|
|
77
|
+
|
|
78
|
+
### Approche
|
|
79
|
+
|
|
80
|
+
Renommage direct en 3 etapes :
|
|
81
|
+
|
|
82
|
+
1. **Fichier source** : `regen.py` → `stale.py`, fonction `regen()` → `stale()`, messages reformules
|
|
83
|
+
2. **Enregistrement CLI** : dans `cli.py`, changer `app.command("regen")` → `app.command("stale")` et l'import correspondant
|
|
84
|
+
3. **References** : commande Claude Code, tests, docs
|
|
85
|
+
|
|
86
|
+
### Modifications des messages
|
|
87
|
+
|
|
88
|
+
| Avant | Apres |
|
|
89
|
+
|-------|-------|
|
|
90
|
+
| `devflow regen — {name}` | `devflow stale — {name}` |
|
|
91
|
+
| `Regenerer ?` | `Voir les commandes de regeneration ?` |
|
|
92
|
+
| `Lancez les commandes suivantes dans l'ordre :` | Inchange (factuel) |
|
|
93
|
+
| `Ou utilisez /devflow.regen pour execution automatique.` | Inchange |
|
|
94
|
+
|
|
95
|
+
### Ce qui ne change PAS
|
|
96
|
+
|
|
97
|
+
- `staleness.py` : module de detection (inchange)
|
|
98
|
+
- `REGEN_COMMANDS` : dictionnaire de mapping artefact → commande (le nom est interne, pas expose a l'utilisateur)
|
|
99
|
+
- `/devflow.regen` (nom de la commande Claude Code) : garde son nom car elle fait la vraie regeneration en cascade. Seul l'appel CLI interne change.
|
|
100
|
+
- Logique de detection, format JSON, options --only et --json
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Research: Fix Regen Command
|
|
2
|
+
|
|
3
|
+
**Branch**: `022-fix-regen-command` | **Date**: 2026-03-21
|
|
4
|
+
|
|
5
|
+
## Renommage vs alias de compatibilite
|
|
6
|
+
|
|
7
|
+
**Decision**: Renommage direct sans alias.
|
|
8
|
+
|
|
9
|
+
**Rationale**: La commande `regen` n'a jamais regenere quoi que ce soit — elle detecte et suggere. Un alias preserverait un nom trompeur. La seule reference externe est `/devflow.regen` (commande Claude Code) qu'on met a jour simultanement.
|
|
10
|
+
|
|
11
|
+
**Alternatives considered**:
|
|
12
|
+
- Alias `regen` → `stale` : preserve la compatibilite mais perpetue la confusion
|
|
13
|
+
- Deprecation warning pendant N versions : over-engineering pour un outil personnel
|
|
14
|
+
|
|
15
|
+
## Nom de la commande Claude Code
|
|
16
|
+
|
|
17
|
+
**Decision**: `/devflow.regen` garde son nom.
|
|
18
|
+
|
|
19
|
+
**Rationale**: Contrairement a la CLI, la commande Claude Code `/devflow.regen` fait reellement la regeneration (elle execute les commandes en cascade). Le nom est donc correct pour elle. Seul l'appel interne change (`devflow stale --json` au lieu de `devflow regen --json`).
|
|
20
|
+
|
|
21
|
+
**Alternatives considered**:
|
|
22
|
+
- Renommer aussi en `/devflow.stale` : incoherent — la commande Claude Code regenere vraiment
|
|
23
|
+
- Creer `/devflow.stale` comme alias de detection pure : inutile — `devflow stale --json` suffit
|
|
24
|
+
|
|
25
|
+
## Nom de la constante REGEN_COMMANDS
|
|
26
|
+
|
|
27
|
+
**Decision**: Garder le nom `REGEN_COMMANDS` dans `staleness.py`.
|
|
28
|
+
|
|
29
|
+
**Rationale**: C'est un nom interne (pas expose a l'utilisateur). Le renommer en `STALE_COMMANDS` ou `REGEN_MAPPING` serait du refactoring cosmétique sans valeur. Constitution Principe V : "Les patterns existants DOIVENT etre suivis."
|
|
30
|
+
|
|
31
|
+
**Alternatives considered**:
|
|
32
|
+
- Renommer en `STALE_COMMANDS` : changement cosmétique, touche plus de fichiers sans benefice
|