# 011.0-DEV-AUTO-UPDATE: Auto-Update package.json

## Release Goal

**Release 0.7: Automated Updates**

Add the ability to automatically update package.json with safe, mature package versions instead of just reporting them. This transforms the tool from a safety checker into a safe updater.

## How This Story Contributes

Completes the safe update workflow by allowing users to apply recommended updates automatically. Reduces manual work and ensures updates are applied consistently according to configured safety policies.

## User Story

**Format**: So that I can automatically update my dependencies to safe versions without manual package.json editing, as a developer, I want dry-aged-deps to update my package.json file with the recommended safe versions when I use an --update flag.

**INVEST Criteria Compliance**:

- **Independent**: Builds on existing filtering logic, adds update capability
- **Negotiable**: Update mode behavior and confirmation flow can be refined
- **Valuable**: Automates the final step in the safe update workflow
- **Estimable**: Clear scope - write package.json updates
- **Small**: Single iteration to add update mode
- **Testable**: Can verify package.json is updated correctly

## Acceptance Criteria

- [ ] **Update Flag**: Accepts `--update` flag to enable auto-update mode
- [ ] **Safe Updates Only**: Only updates packages that pass maturity and security filters
- [ ] **Preserve Format**: Maintains package.json formatting and property order
- [ ] **Preview and Confirm**: Shows what would be updated and requires confirmation before applying changes
- [ ] **Yes Flag**: Accepts `--yes` flag to skip confirmation and apply updates immediately
- [ ] **Backup**: Creates backup of package.json before updating (optional but recommended)
- [ ] **Install Prompt**: Prompts user to run `npm install` after updates
- [ ] **Summary Report**: Shows summary of what was updated
- [ ] **Error Handling**: Gracefully handles file write errors

## Requirements (Current Implementation or To Be Implemented)

- **REQ-UPDATE-FLAG**: Support `--update` CLI flag to enable update mode
- **REQ-YES-FLAG**: Support `--yes` or `-y` flag to skip confirmation
- **REQ-PREVIEW**: When `--update` is used alone, show preview of changes and prompt for confirmation
- **REQ-SAFE-ONLY**: Only update packages that meet maturity and security criteria. The version written to `package.json` is the `latest` version reported by `npm outdated` (or the highest mature, vulnerability-free version found by the smart-search fallback) — NOT the semver-range-satisfying `wanted` version. See ADR-0014 (`docs/decisions/0014-update-target-is-latest-safe-not-wanted.proposed.md`) for the disambiguation. The written value is an exact version string (no caret, no tilde); the trust model is that the specific version is safe, not that future versions in any range will be.
- **REQ-PACKAGE-JSON**: Read, modify, and write package.json
- **REQ-FORMAT-PRESERVE**: Maintain original formatting (use 2-space indent, preserve property order)
- **REQ-CONFIRMATION**: Interactive confirmation prompt unless `--yes` provided
- **REQ-BACKUP**: Create `package.json.backup` before updating (optional)
- **REQ-SUMMARY**: Display summary of updated packages
- **REQ-POST-UPDATE**: After writing `package.json`, reconcile `package-lock.json` in the same run by spawning `npm install --ignore-scripts --package-lock-only` (incremental — no `node_modules` install, no lifecycle scripts) so the project is immediately installable via `npm ci --prefer-frozen-lockfile`. Fail loud on reconcile error (surface it and reflect it in the exit code). Runs only when ≥1 update was applied. See ADR-0021 (`docs/decisions/0021-update-reconciles-package-lock-via-incremental-install.proposed.md`) / RFC-003 (traces P030).

## Dependencies

- **001.0-DEV-RUN-NPM-OUTDATED**: Need list of outdated packages
- **003.0-DEV-IDENTIFY-OUTDATED**: Need mature version filtering
- **004.0-DEV-FILTER-VULNERABLE-VERSIONS**: Need vulnerability filtering

## Usage Examples

**Preview mode (default)**:

```bash
dry-aged-deps --update
# Shows what would be updated, requires confirmation
# Output:
# The following packages will be updated:
#   express: 4.17.1 → 4.18.2 (45 days old, no vulnerabilities)
#   lodash: 4.17.20 → 4.17.21 (30 days old, no vulnerabilities)
#
# Update package.json? [y/N]
```

**Auto-confirm mode**:

```bash
dry-aged-deps --update --yes
# Updates package.json without confirmation
# Output:
# Updated package.json with 2 safe packages
# Run 'npm install' to install the updates
```

## Definition of Done

- [ ] All acceptance criteria met
- [ ] Code reviewed and approved
- [ ] Unit tests for package.json reading/writing
- [ ] Unit tests for format preservation
- [ ] Tests for confirmation flow
- [ ] Tests for backup creation
- [ ] Integration tests with real package.json files
- [ ] Documentation updated (README.md shows --update usage)
- [ ] Help text includes --update and --yes flags
- [ ] Error handling tested for all failure scenarios
- [ ] Backward compatible (no --update = read-only behavior)

---

## Story Notes

**Gall's Law Compliance**: Adds update capability to working read-only system. Default behavior unchanged - tool remains read-only unless --update specified.

**Safety First**: Only updates packages that pass all configured filters. Never updates to vulnerable or immature versions.

**User Control**: Requires explicit flag and confirmation. No surprises, no silent updates.

**Backup Strategy**: Consider creating backup file before updates. Users can restore if something goes wrong.

**npm install (amended ADR-0021, 2026-07-08)**: `--update` writes package.json AND reconciles package-lock.json via `npm install --ignore-scripts --package-lock-only` — a lockfile-metadata-only sync (no `node_modules` install, no lifecycle scripts) so the result is immediately `npm ci`-installable. This supersedes the original "doesn't run npm install automatically" intent in spirit: node_modules is still NOT installed and no scripts run (the changes stay a reviewable diff), but the lockfile is now kept in sync — closing P030, where a stale lockfile broke adopters' `npm ci`.

**Future Enhancement**: Updating package-lock.json directly is now DONE (ADR-0021). Optionally running a full `npm install` (installing node_modules) behind a flag remains deferred — ADR-0021 declined the opt-out flag per ADR-0014's YAGNI bar; revisit if a persona needs it.

**Alternative Flag Names**: Could use `--apply`, `--write`, or `--fix` instead of `--update` - team preference.
