Skip to content

feat(tasks): add scope lifecycle task commands for vBRIEF model (#324)#339

Merged
MScottAdams merged 3 commits intophase2/vbrief-cutoverfrom
agent5/feat/324-scope-lifecycle
Apr 13, 2026
Merged

feat(tasks): add scope lifecycle task commands for vBRIEF model (#324)#339
MScottAdams merged 3 commits intophase2/vbrief-cutoverfrom
agent5/feat/324-scope-lifecycle

Conversation

@MScottAdams
Copy link
Copy Markdown
Collaborator

Summary

Add deterministic task commands for all vBRIEF scope lifecycle transitions per RFC #309 decision D16.

Changes

  • scripts/scope_lifecycle.py: Main script implementing 7 lifecycle transitions (promote, activate, complete, cancel, restore, block, unblock). Each validates legal transitions, updates plan.status and plan.updated, moves file to target lifecycle folder.
  • ** asks/scope.yml**: Taskfile definitions for scope:promote, scope:activate, scope:complete, scope:cancel, scope:restore, scope:block, scope:unblock.
  • Taskfile.yml: Added scope include entry.
  • ** ests/cli/test_scope_lifecycle.py**: 38 tests covering all transitions, invalid transitions, idempotent behavior, validation edge cases, full lifecycle round-trips, and CLI subprocess integration.
  • CHANGELOG.md: Entry under [Unreleased].

Transition Matrix

Command Source Target Status
promote proposed/ pending/ pending
activate pending/ active/ running
complete active/ completed/ completed
cancel any/ cancelled/ cancelled
restore cancelled/ proposed/ proposed
block active/ (stays) active/ blocked
unblock active/ (stays) active/ running

Testing

  • 38 unit + integration tests, all passing
  • task check passes (1055 tests, 0 failures)
  • Block/unblock idempotent (no-op if already in target state)
  • Target folders auto-created if missing

Checklist

  • CHANGELOG.md updated
  • task check passes
  • Tests cover new code paths (38 tests)
  • Works on Windows (PowerShell 5.1) and Unix

Part of #309. Closes #324. Tracking: #338.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 13, 2026

Greptile Summary

This PR implements 7 deterministic vBRIEF scope lifecycle transition commands (scope:promote, scope:activate, scope:complete, scope:cancel, scope:restore, scope:block, scope:unblock) per RFC #309 decision D16. It also addresses all three P0/P1 findings from the prior review round: the wrong label for idempotent cancel, the Path.rename() Windows incompatibility, and the premature timestamp write before the same-folder guard — all resolved correctly in the current HEAD.

Confidence Score: 5/5

Safe to merge — all three prior P0/P1 findings are resolved; only a minor test-docstring gap remains.

The wrong-label bug, the Windows Path.rename incompatibility, and the premature timestamp write are all fixed correctly in the current HEAD. The remaining finding is a P2 test-quality nit (missing assertion to back a docstring claim) that does not affect runtime correctness.

tests/cli/test_scope_lifecycle.py — minor assertion gap in test_cancel_already_cancelled_is_noop.

Important Files Changed

Filename Overview
scripts/scope_lifecycle.py Core lifecycle transition engine; prior review findings (wrong label, Path.rename Windows bug, premature timestamp write) all addressed with an early-return idempotency guard at line 140 and Path.replace() at line 161.
tests/cli/test_scope_lifecycle.py 38 tests covering all 7 transitions, idempotency, edge cases, and CLI subprocess; test_cancel_already_cancelled_is_noop documents "no timestamp mutation" in its docstring but does not assert the absence of an updated field.
tasks/scope.yml Seven Taskfile task definitions wiring CLI_ARGS to scope_lifecycle.py; consistent with project conventions and correctly namespaced via the root include key.
Taskfile.yml Adds the scope include entry with optional: true; no other changes, consistent with existing pattern.
CHANGELOG.md Adds Unreleased entry for scope lifecycle commands per project convention; well-formed and complete.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    PROPOSED["proposed/\nstatus: proposed"]
    PENDING["pending/\nstatus: pending"]
    ACTIVE_R["active/\nstatus: running"]
    ACTIVE_B["active/\nstatus: blocked"]
    COMPLETED["completed/\nstatus: completed"]
    CANCELLED["cancelled/\nstatus: cancelled"]

    PROPOSED -->|"scope:promote"| PENDING
    PENDING -->|"scope:activate"| ACTIVE_R
    ACTIVE_R -->|"scope:block"| ACTIVE_B
    ACTIVE_B -->|"scope:unblock"| ACTIVE_R
    ACTIVE_R -->|"scope:complete"| COMPLETED
    ACTIVE_B -->|"scope:complete"| COMPLETED
    PROPOSED -->|"scope:cancel"| CANCELLED
    PENDING -->|"scope:cancel"| CANCELLED
    ACTIVE_R -->|"scope:cancel"| CANCELLED
    ACTIVE_B -->|"scope:cancel"| CANCELLED
    COMPLETED -->|"scope:cancel"| CANCELLED
    CANCELLED -->|"scope:restore"| PROPOSED
Loading
Prompt To Fix All With AI
This is a comment left during a code review.
Path: tests/cli/test_scope_lifecycle.py
Line: 179-185

Comment:
**Docstring claims "no timestamp mutation" but assertion is absent**

The docstring says `no timestamp mutation`, yet the test only checks `ok`, the `"No-op"` prefix, and file existence. It never reads the file back to confirm `"updated"` was not added. Since `make_vbrief` omits the `updated` field, a single extra assert would close this gap:

```suggestion
    def test_cancel_already_cancelled_is_noop(self, tmp_path):
        """Cancel from cancelled/ is idempotent — no-op, no timestamp mutation."""
        f = make_vbrief(tmp_path, "cancelled", "cancelled")
        ok, msg = run_transition("cancel", f)
        assert ok
        assert "No-op" in msg
        assert f.exists()
        assert "updated" not in read_vbrief(f)["plan"]
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (3): Last reviewed commit: "fix: address Greptile review findings (b..." | Re-trigger Greptile

Comment thread scripts/scope_lifecycle.py
Comment thread scripts/scope_lifecycle.py Outdated
Comment thread scripts/scope_lifecycle.py
- Create scripts/scope_lifecycle.py with 7 deterministic lifecycle transitions
  (promote, activate, complete, cancel, restore, block, unblock)
- Each command validates legal transitions, updates plan.status and plan.updated,
  moves file to target lifecycle folder (or stays in place for block/unblock)
- Invalid transitions rejected with descriptive error messages
- Block/unblock are idempotent (no-op if already in target state)
- Target folders created automatically if missing
- Create tasks/scope.yml with all 7 task definitions
- Add scope include to Taskfile.yml
- Create tests/cli/test_scope_lifecycle.py with 38 tests covering all transitions,
  invalid transitions, idempotent behavior, validation edge cases, full lifecycle
  round-trips, and CLI subprocess integration
- Add CHANGELOG.md entry under [Unreleased]

Part of #309. Closes #324. Tracking: #338.
- Fix E501 line-too-long in scope_lifecycle.py error message formatting
- Fix UP017 use datetime.UTC alias instead of timezone.utc
- Fix RET505 remove unnecessary else after return in main()
- Remove unused os import from test_scope_lifecycle.py
- Remove unused TRANSITIONS import from test_scope_lifecycle.py
- Fix I001 import sorting in test_scope_lifecycle.py
- P1: cancel-from-cancelled now returns No-op instead of wrong 'Unblocked' label;
  added idempotency early-return for same-folder moves before file write
- P2: Timestamp no longer mutated for idempotent same-folder transitions
- P2: Use Path.replace() instead of Path.rename() for Windows portability
  (Path.rename raises FileExistsError on Windows if destination exists)
- Updated test_cancel_already_cancelled to assert on No-op message
@MScottAdams MScottAdams force-pushed the agent5/feat/324-scope-lifecycle branch from afc2324 to 0c1b76b Compare April 13, 2026 19:09
@MScottAdams MScottAdams merged commit 05b6708 into phase2/vbrief-cutover Apr 13, 2026
2 checks passed
@MScottAdams MScottAdams deleted the agent5/feat/324-scope-lifecycle branch April 13, 2026 19:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant