Skip to content

Add update command for a project's description and scores - #56

Merged
dmccoystephenson merged 1 commit into
mainfrom
feat/update-command
Oct 1, 2026
Merged

dmccoystephenson merged 1 commit into
mainfrom
feat/update-command

Conversation

@dmccoystephenson

Copy link
Copy Markdown
Member

Summary

  • A new update <project-name> shell command (UpdateProjectCommand) is added. It changes a project's description and/or any of its five scores through --description/-d, --impact/-i, --confidence/-c, --ease/-e, --reach/-r and --effort/-f. These are the same short flags create uses. Fields that are not given keep their current values, and the new ICE and RICE scores are printed.
  • Invalid input is rejected before anything is changed: a call with nothing to update, an empty description, or a score outside 1-5. These use the same messages as create. An unknown name is reported as Project not found: <name>, matching view and delete.
  • ProjectService.updateProject builds the changed project, treating a null argument as "keep the current value". ProjectRepository.update swaps it in at the same index, so the project keeps its place in creation order, and writes the JSON once.
  • The README lists update under "Available commands" and gets an "Update Examples" section.
  • Renaming is deliberately left out of scope, because a rename would need its own name-taken handling. The README states that update cannot rename a project.

Test plan

  • ./gradlew test (JDK 21): 136 tests executed, 0 failures, 0 errors. The count comes from the summed build/test-results/test/*.xml.
  • UpdateProjectCommandTest (7 tests) covers partial updates, the success message, keeping position among other projects, persistence to storage, nothing-to-update, empty description, out-of-range scores (high and low) leaving the project unchanged, and an unknown name.
  • ProjectServiceTest (+3) covers updating only the given fields, distinct values on every field to catch transposed arguments, and an unknown name never reaching update.
  • ProjectRepositoryTest (+2) covers in-place replacement with a single write, and an unknown name throwing without a write.
  • The built jar was run manually with a throwaway app.projects.file: create, then update Demo --impact 5 -d "New desc", then view Demo, plus update Demo, update Demo -f 9 and update Ghost -i 2. Each printed the expected output, which confirms the positional name and options parse in Spring Shell.

Deferred issues

Closes #21

This PR description was drafted during a Gardener session (https://github.com/Stephenson-Software/gardener).

🤖 Generated with Claude Code


drafted by Claude on behalf of Daniel Stephenson

A new `update <project-name>` shell command changes a project's
description and/or any of its five scores; fields not given keep their
current values. It rejects a call with nothing to change, an empty
description, or a score outside 1-5, and reports an unknown name the
same way `view` and `delete` do. ProjectService.updateProject builds the
changed project and ProjectRepository.update replaces it in place, so it
keeps its creation-order position, and persists it. The README lists the
command with examples.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown

Test Results

136 tests  +12   136 ✅ +12   2s ⏱️ ±0s
 20 suites + 1     0 💤 ± 0 
 20 files   + 1     0 ❌ ± 0 

Results for commit 94a958e. ± Comparison against base commit b42a62a.

@dmccoystephenson

Copy link
Copy Markdown
Member Author

Self-review rubric (performed inline in the same session; no independent reviewer was available):

  • Scope: PASS. All 7 changed files serve Update command #21: the command, the service and repository methods it needs, their tests, and the README. The diff only adds lines; it deletes nothing.
  • Tests-new: PASS. Each new public method has direct tests. UpdateProjectCommand.execute has 7 tests in UpdateProjectCommandTest, ProjectService.updateProject has 3 new tests, and ProjectRepository.update has 2.
  • Tests-fix: N/A. Update command #21 is a feature request, not a bug fix, so the stash-and-run check does not apply.
  • Sibling structure: PASS. UpdateProjectCommand follows the shape of DeleteProjectCommand/ViewProjectCommand: constructor injection, a single execute, and the same Project not found: <name> message. Its option flags reuse create's short flags. UpdateProjectCommandTest copies DeleteProjectCommandTest's @SpringBootTest setup, given/when/then comments and should… naming. The new repository and service tests use their files' method_ShouldBehavior naming.
  • Sibling renames: N/A. Nothing is renamed.
  • Docs: PASS. The README "Available commands" list and a new "Update Examples" section were checked against the implementation, including the flags, the messages, persistence, the kept position, and the fact that renaming is not supported. CONTRIBUTING.md's ./gradlew test is unchanged and still accurate. No Roadmap item corresponds to this feature.
  • Issue resolution: PASS. Update command #21 ("Update command") has no body, so its surface is read as "an update command exists". This PR adds one.
  • Manual validation: PASS. Locally, ./gradlew test on JDK 21 executed 136 tests with 0 failures (summed from the JUnit XML). On the PR head, test, build (21) and Test Results are green. The built jar was also driven end to end with a throwaway data file.
  • Shell command tests: PASS. The new @ShellComponent has UpdateProjectCommandTest.
  • Round-trip coverage: N/A. No field is added to Project.
  • I/O behind an interface: PASS. No new I/O is introduced. Persistence goes through the existing ProjectJsonReaderWriter via ProjectRepository.

Judgment notes (non-blocking):

  • src/main/java/com/preponderous/parpt/command/UpdateProjectCommand.java:45: the 1-5 range check now exists in both CreateProjectCommand and UpdateProjectCommand. Moving it into a shared validator fits naturally under Input validation w/ Jakarta #8 (Input validation w/ Jakarta). It was not done here so that this PR stays within Update command #21.
  • src/main/java/com/preponderous/parpt/repo/ProjectRepository.java:44: indexOf relies on Lombok value equality. This is safe only because add enforces unique names, so exactly one element can match the instance that findByName returns.
  • A description made only of whitespace is accepted, the same as in create, which also checks only isEmpty(). This was kept consistent rather than diverging.

Verdict: ready to merge. No protected paths are touched (build.gradle, application.yaml and .github/workflows/* are unchanged).

This review was drafted during a Gardener session (https://github.com/Stephenson-Software/gardener).


drafted by Claude on behalf of Daniel Stephenson

@dmccoystephenson
dmccoystephenson merged commit 784e3c5 into main Oct 1, 2026
3 checks passed
@dmccoystephenson
dmccoystephenson deleted the feat/update-command branch October 1, 2026 07:48
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.

Update command

1 participant