From ba05908cc401f9a50d794a2ba8decc0ff5f58046 Mon Sep 17 00:00:00 2001 From: AI Bot Date: Mon, 13 Apr 2026 16:36:17 +0200 Subject: [PATCH] Update openspec with clarified design decisions --- openspec/changes/declpac-cli-tool/design.md | 51 +++++++++++++--- .../declpac-cli-tool/specs/aur-sync/spec.md | 29 +++++---- .../specs/machine-output/spec.md | 37 +++++++----- .../specs/pacman-query/spec.md | 22 +++++++ .../specs/state-validation/spec.md | 31 ++++++---- openspec/changes/declpac-cli-tool/tasks.md | 60 ++++++++++++------- 6 files changed, 164 insertions(+), 66 deletions(-) create mode 100644 openspec/changes/declpac-cli-tool/specs/pacman-query/spec.md diff --git a/openspec/changes/declpac-cli-tool/design.md b/openspec/changes/declpac-cli-tool/design.md index 30cbbbd..fa562df 100644 --- a/openspec/changes/declpac-cli-tool/design.md +++ b/openspec/changes/declpac-cli-tool/design.md @@ -38,18 +38,35 @@ package list, with all packages at their latest available versions. **Input Parsing Approach** - Parse whitespace, tabs, newlines for package names - Support multiple --state files: all additive including with stdin -- Validate package names against pacman available packages (optional validation) - Empty state detection: print error to stderr and exit with code 1 (abort) +**Package Database Freshness** +- Use libalpm (dyalpm) to check last sync time from /var/lib/pacman/db.lock timestamp +- If database older than 1 day, run `pacman -Syy` to refresh before validation +- Refresh happens before validation and sync operations + +**Package Validation** +- Validate all declared packages exist in pacman repos or AUR before sync +- Use libalpm (dyalpm) for pacman repo queries (fast local DB access) +- Use Jguer/aur library for AUR queries +- Fail fast with clear error if any package not found +- Let pacman report detailed errors during sync (don't duplicate validation) + **State Merging Logic** - All inputs are additive: combine all packages from stdin and all state files - No conflict resolution: missing packages are added, duplicates accumulate - Order-independent: inputs don't override each other -**Pacman Interaction** -- Use os/exec.Command to run pacman with -Sy (sync databases) and -S flag -- Run pacman -Syu with all target packages to ensure full upgrade -- Capture stderr/stdout for error reporting and machine output +**Hybrid Query/Modify Approach** +- **Query operations**: Use libalpm (dyalpm) for fast local package database access + - Query installed packages, available packages, package details + - Check database freshness (last sync time) +- **Modify operations**: Use os/exec.Command to run pacman commands + - pacman -Syy: Refresh package databases + - pacman -Syu: Install/upgrade packages (full upgrade) + - pacman -D --explicit: Mark packages as explicitly installed + - pacman -Rns: Remove orphaned packages +- Capture stderr/stdout for error reporting and output generation - Detect pacman exit codes and translate to tool exit codes **Error Handling Strategy** @@ -59,11 +76,13 @@ package list, with all packages at their latest available versions. - Include error details in output for scripting purposes **AUR Integration** -- For packages not found in pacman repositories, check if available in AUR -- Use makepkg directly to build and install AUR packages (no AUR helpers) +- First attempt: Try pacman -Syu for all packages (includes AUR auto-install if enabled) +- For packages not found in pacman repos: Check AUR via Jguer/aur library +- If package in AUR: Build and install with makepkg (no AUR helpers) +- AUR packages should also upgrade to latest version (no partial updates) - Clone AUR git repo to temp directory - Run `makepkg -si` in temp directory for installation -- Capture stdout/stderr for output and error handling +- Capture stdout/stderr for output parsing - Report error to stderr if package not found in pacman or AUR **Dependency Resolution** @@ -86,6 +105,18 @@ package list, with all packages at their latest available versions. - Pacman handles version selection automatically, ensuring latest versions - No semantic version comparison or pinning logic required +**CLI Interface** +- Usage: `declpac --state file1.txt --state file2.txt < stdin` +- Multiple --state flags allowed, all additive +- Stdin input via standard input stream +- No interactive prompts - fully automated + +**Output Format** +- Success: Print to stdout: `Installed X packages, removed Y packages` +- No changes: Print `Installed 0 packages, removed 0 packages` +- Errors: Print error message to stderr +- Exit codes: 0 for success, 1 for errors + ## Risks / Trade-offs **Known Risks:** @@ -99,6 +130,10 @@ package list, with all packages at their latest available versions. design choice; pacman handles duplicates gracefully - [Dependency conflicts could occur] → Mitigation: Let pacman handle standard conflicts; tool won't implement complex dependency resolution +- [libalpm integration complexity] → Mitigation: Use dyalpm wrapper library; + validate queries work before build +- [AUR package build failures] → Mitigation: Capture makepkg output, report errors + to stderr; don't retry **Trade-offs:** - No conflict resolution: simpler merging but may include packages the system diff --git a/openspec/changes/declpac-cli-tool/specs/aur-sync/spec.md b/openspec/changes/declpac-cli-tool/specs/aur-sync/spec.md index 011ea1f..36cb489 100644 --- a/openspec/changes/declpac-cli-tool/specs/aur-sync/spec.md +++ b/openspec/changes/declpac-cli-tool/specs/aur-sync/spec.md @@ -1,23 +1,30 @@ ## ADDED Requirements -### Requirement: Can handle AUR packages with pacman fallback +### Requirement: Handle AUR packages with fallback and upgrade -The system SHALL attempt to install AUR packages by first trying pacman -repositories, then falling back to AUR when pacman fails, and finally reporting -errors for packages still missing. +The system SHALL first attempt to install packages via pacman, then fall back +to AUR for packages not found in repos, and upgrade AUR packages to +latest versions. -#### Scenario: Install from pacman first +#### Scenario: Try pacman first - **WHEN** package is in pacman repositories -- **THEN** system shall install via pacman +- **THEN** install via pacman -Syu #### Scenario: Fall back to AUR - **WHEN** package is not in pacman repositories but is in AUR -- **THEN** system shall attempt installation via makepkg (direct AUR build) +- **THEN** query AUR via Jguer/aur library +- **AND** build and install with makepkg -si + +#### Scenario: Upgrade AUR packages +- **WHEN** AUR package is already installed but outdated +- **THEN** rebuild and reinstall with makepkg to get latest version #### Scenario: Report error for missing packages - **WHEN** package is not in pacman repositories or AUR -- **THEN** system shall report error and print to stderr +- **THEN** print error to stderr with package name +- **AND** exit with code 1 -#### Scenario: Continue for remaining packages -- **WHEN** some packages are installed and some fail -- **THEN** system shall continue installation process for successful packages +#### Scenario: AUR build failure +- **WHEN** makepkg fails to build package +- **THEN** print makepkg error to stderr +- **AND** exit with code 1 \ No newline at end of file diff --git a/openspec/changes/declpac-cli-tool/specs/machine-output/spec.md b/openspec/changes/declpac-cli-tool/specs/machine-output/spec.md index f8627f2..570fea6 100644 --- a/openspec/changes/declpac-cli-tool/specs/machine-output/spec.md +++ b/openspec/changes/declpac-cli-tool/specs/machine-output/spec.md @@ -1,21 +1,30 @@ ## ADDED Requirements -### Requirement: Can generate machine-readable output +### Requirement: Generate consistent output format -The system SHALL produce output suitable for automated scripting. +The system SHALL produce console output suitable for logging and scripting. -#### Scenario: Install/remove count output -- **WHEN** sync completes successfully -- **THEN** system shall output: " package(s) installed, package(s) removed" +#### Scenario: Successful sync with changes +- **WHEN** sync completes with packages installed or removed +- **THEN** print to stdout: `Installed X packages, removed Y packages` +- **AND** exit with code 0 -#### Scenario: Empty output format -- **WHEN** no packages to sync -- **THEN** system shall output nothing (or indicate no changes) +#### Scenario: No changes needed +- **WHEN** all packages already match declared state +- **THEN** print to stdout: `Installed 0 packages, removed 0 packages` +- **AND** exit with code 0 -#### Scenario: Error details in output -- **WHEN** pacman operation fails -- **THEN** system shall include error details in output (package names, pacman error messages) +#### Scenario: Error during sync +- **WHEN** pacman or makepkg operation fails +- **THEN** print error to stderr with details +- **AND** exit with code 1 -#### Scenario: Exit code for scripting -- **WHEN** sync completes -- **THEN** system shall return exit code 0 for success, non-zero for errors \ No newline at end of file +#### Scenario: Validation failure +- **WHEN** package validation fails (package not in pacman or AUR) +- **THEN** print error to stderr with package name +- **AND** exit with code 1 + +#### Scenario: Empty state input +- **WHEN** no packages provided from stdin or state files +- **THEN** print error to stderr: `empty state input` +- **AND** exit with code 1 \ No newline at end of file diff --git a/openspec/changes/declpac-cli-tool/specs/pacman-query/spec.md b/openspec/changes/declpac-cli-tool/specs/pacman-query/spec.md new file mode 100644 index 0000000..8755c37 --- /dev/null +++ b/openspec/changes/declpac-cli-tool/specs/pacman-query/spec.md @@ -0,0 +1,22 @@ +## ADDED Requirements + +### Requirement: Query pacman package database via libalpm + +The system SHALL use libalpm for fast local queries against the pacman +package database. + +#### Scenario: Query installed packages +- **WHEN** needing list of currently installed packages +- **THEN** query via libalpm alpm_list_get(ALPM_LIST_PACKAGES) + +#### Scenario: Query available packages +- **WHEN** validating package exists in pacman repos +- **THEN** query via libalpm alpm_db_get_pkg() + +#### Scenario: Check database last sync time +- **WHEN** checking if database needs refresh +- **THEN** check /var/lib/pacman/db.lock timestamp + +#### Scenario: Query foreign packages +- **WHEN** checking if package is AUR-installed +- **THEN** query via libalpm alpm_db_get_pkg(ALPM_DB_TYPE_LOCAL) \ No newline at end of file diff --git a/openspec/changes/declpac-cli-tool/specs/state-validation/spec.md b/openspec/changes/declpac-cli-tool/specs/state-validation/spec.md index 9017fef..fedf0d3 100644 --- a/openspec/changes/declpac-cli-tool/specs/state-validation/spec.md +++ b/openspec/changes/declpac-cli-tool/specs/state-validation/spec.md @@ -1,17 +1,28 @@ ## ADDED Requirements -### Requirement: Can detect empty state input +### Requirement: Validate package names exist in pacman or AUR -The system SHALL detect when no packages are provided in any input source. +The system SHALL validate that all declared packages exist in pacman +repositories or AUR before attempting to sync. -#### Scenario: Empty state warning +#### Scenario: Empty state detection - **WHEN** no package names are found in stdin or state files -- **THEN** system shall print a warning to stderr +- **THEN** print error to stderr: `empty state input` +- **AND** exit with code 1 -#### Scenario: Empty state warning message -- **WHEN** warning is printed for empty state -- **THEN** message shall say: "Called without state, aborting.." +#### Scenario: Validate package in pacman repos +- **WHEN** package exists in pacman repositories +- **THEN** validation passes -#### Scenario: Abort on empty state -- **WHEN** empty state is detected -- **THEN** system shall exit with code 1 (error: no packages to sync) +#### Scenario: Validate package in AUR +- **WHEN** package not in pacman repos but exists in AUR +- **THEN** validation passes + +#### Scenario: Package not found +- **WHEN** package not in pacman repos or AUR +- **THEN** print error to stderr with package name +- **AND** exit with code 1 + +#### Scenario: Database freshness check +- **WHEN** pacman database last sync was more than 1 day ago +- **THEN** run pacman -Syy to refresh before validation \ No newline at end of file diff --git a/openspec/changes/declpac-cli-tool/tasks.md b/openspec/changes/declpac-cli-tool/tasks.md index ae728e9..502b023 100644 --- a/openspec/changes/declpac-cli-tool/tasks.md +++ b/openspec/changes/declpac-cli-tool/tasks.md @@ -1,8 +1,9 @@ ## 1. Project Setup - [ ] 1.1 Initialize Go module with proper imports -- [ ] 1.2 Add required dependencies (libalpm wrapper) -- [ ] 1.3 Set up project structure (main.go, pkg/ subdirectory) +- [ ] 1.2 Add required dependencies (dyalpm wrapper, Jguer/aur) +- [ ] 1.3 Set up project structure (cmd/declpac/main.go, pkg/ subdirectory) +- [ ] 1.4 Add libalpm initialization and handle ## 2. Input Parsing @@ -22,16 +23,24 @@ - [ ] 4.1 Implement empty state detection (no packages found) - [ ] 4.2 Add stderr error output for empty state - [ ] 4.3 Set exit code 1 for empty state case (abort, not proceed) - -## 5. Pacman Integration - -- [ ] 5.1 Implement pacman -Syu command execution wrapper -- [ ] 5.2 Add command-line argument construction with package list -- [ ] 5.3 Capture pacman stdout and stderr output -- [ ] 5.4 Implement pacman error message parsing -- [ ] 5.5 Handle pacman exit codes for success/failure detection -- [ ] 5.6 Verify pacman automatically resolves transitive dependencies -- [ ] 5.7 Verify shared dependencies are deduplicated by pacman +- [ ] 4.4 Check pacman DB freshness (db.lock timestamp) +- [ ] 4.5 Run pacman -Syy if DB older than 1 day +- [ ] 4.6 Validate packages via libalpm (pacman repos) +- [ ] 4.7 Validate packages via Jguer/aur (AUR) +- [ ] 4.8 Fail fast with error if package not found + +## 5. Pacman Integration (Hybrid: query via libalpm, modify via exec) + +- [ ] 5.1 Initialize libalpm handle for queries +- [ ] 5.2 Implement libalpm query for installed packages +- [ ] 5.3 Implement libalpm query for available packages +- [ ] 5.4 Implement pacman -Syy command execution (DB refresh) +- [ ] 5.5 Implement pacman -Syu command execution wrapper +- [ ] 5.6 Add command-line argument construction with package list +- [ ] 5.7 Capture pacman stdout and stderr output +- [ ] 5.8 Implement pacman error message parsing +- [ ] 5.9 Handle pacman exit codes for success/failure detection +- [ ] 5.10 Verify pacman automatically resolves transitive dependencies ## 6. Explicit Marking & Orphan Cleanup @@ -44,20 +53,25 @@ ## 7. AUR Integration -- [ ] 7.1 Implement AUR package lookup via package query (Jguer/aur) -- [ ] 7.2 Add pacman first attempt (package not in repos) -- [ ] 7.3 Implement AUR fallback using makepkg (direct build, not AUR helper) -- [ ] 7.4 Clone AUR package git repo to temp directory -- [ ] 7.5 Run makepkg -si in temp directory for installation -- [ ] 7.6 Add stderr error reporting for packages not in pacman or AUR -- [ ] 7.7 Capture makepkg stdout and stderr for output parsing -- [ ] 7.8 Handle makepkg exit codes for success/failure detection +- [ ] 7.1 Implement AUR package lookup via Jguer/aur library +- [ ] 7.2 Check package not in pacman repos first (via libalpm) +- [ ] 7.3 Query AUR for missing packages +- [ ] 7.4 Implement AUR fallback using makepkg (direct build, not AUR helper) +- [ ] 7.5 Clone AUR package git repo to temp directory +- [ ] 7.6 Run makepkg -si in temp directory for installation +- [ ] 7.7 Upgrade existing AUR packages to latest (makepkg rebuild) +- [ ] 7.8 Add stderr error reporting for packages not in pacman or AUR +- [ ] 7.9 Capture makepkg stdout and stderr for output parsing +- [ ] 7.10 Handle makepkg exit codes for success/failure detection ## 8. Output Generation -- [ ] 8.1 Capture installed/removed package counts from pacman output -- [ ] 8.2 Generate machine-readable output line in requested format -- [ ] 8.3 Include error details in output on failure +- [ ] 8.1 Parse pacman output for installed package count +- [ ] 8.2 Parse pacman output for removed package count (orphan cleanup) +- [ ] 8.3 Generate output: `Installed X packages, removed Y packages` +- [ ] 8.4 Handle 0 packages case: `Installed 0 packages, removed 0 packages` +- [ ] 8.5 Print errors to stderr +- [ ] 8.6 Set exit code 0 for success, 1 for errors ## 9. CLI Interface