Browse Source

Add OpenSpec change for operation logging

master
AI Bot 3 days ago committed by Riyyi
parent
commit
0b834214cd
  1. 2
      openspec/changes/add-operation-logging/.openspec.yaml
  2. 66
      openspec/changes/add-operation-logging/design.md
  3. 26
      openspec/changes/add-operation-logging/proposal.md
  4. 45
      openspec/changes/add-operation-logging/tasks.md

2
openspec/changes/add-operation-logging/.openspec.yaml

@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-04-15

66
openspec/changes/add-operation-logging/design.md

@ -0,0 +1,66 @@
## Implementation
### Log File Location
- Path: `/var/log/declpac.log`
- Single merged log file (stdout + stderr intermingled in order of arrival)
### State-Modifying Functions (need logging)
1. `SyncPackages()` - `pacman -S --needed <packages>`
2. `InstallAUR()` - `git clone` + `makepkg -si --noconfirm`
3. `MarkAllAsDeps()` - `pacman -D --asdeps`
4. `MarkAsExplicit()` - `pacman -D --asexplicit <packages>`
5. `CleanupOrphans()` - `pacman -Rns`
### Functions to Skip (read-only)
- `DryRun()` - queries only
- `getInstalledCount()` - pacman -Qq
### Execution Patterns
| Pattern | Functions | How |
|---------|------------|-----|
| Streaming | MarkAllAsDeps, MarkAsExplicit, InstallAUR | `io.MultiWriter` to tee to both terminal and log |
| Captured | SyncPackages, CleanupOrphans | capture with `CombinedOutput()`, write to log, write to terminal |
### Error Handling
- Write error to log BEFORE returning from function
- Print error to stderr so user sees it
### Dependencies
- Add to imports: `io`, `os`, `path/filepath`
### Structure
```go
// pkg/state/state.go
var logFile *os.File
func OpenLog() error {
logPath := filepath.Join("/var/log", "declpac.log")
f, err := os.OpenFile(logPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return err
}
logFile = f
return nil
}
func GetLogWriter() io.Writer {
return logFile
}
func Close() error {
if logFile == nil {
return nil
}
return logFile.Close()
}
```
### Flow in Sync() or main entrypoint
1. Call `OpenLog()` at program start, defer close
2. Each state-modifying function uses `state.GetLogWriter()` via MultiWriter
### Wire into main.go
- Open log at start of `run()`
- Pass log writer to pacman package (via exported function or global)

26
openspec/changes/add-operation-logging/proposal.md

@ -0,0 +1,26 @@
## Why
The tool exits without saving the full pacman output, making debugging difficult
when operations fail. Users need a persistent log of all pacman operations for
debugging and audit.
## What Changes
- Add state directory initialization creating `~/.local/state/declpac` if not exists
- Open/manage a single log file at `$XDG_STATE_HOME/declpac` (e.g., `~/.local/state/declpac/declpac`)
- Instrument all state-modifying exec calls in `pkg/pacman/pacman.go` to tee or append output to this file
- Skip debug messages (internal timing logs)
- Capture and write errors before returning
## Capabilities
### New Capabilities
- Operation logging: Persist stdout/stderr from all pacman operations
### Modified Capabilities
- None
## Impact
- `pkg/pacman/pacman.go`: Instrument all state-modifying functions to write to log file
- New module: May create `pkg/state/state.go` or similar for log file management

45
openspec/changes/add-operation-logging/tasks.md

@ -0,0 +1,45 @@
## Tasks
- [x] 1. Create state module
Create `pkg/state/state.go`:
- `OpenLog()` - opens `/var/log/declpac.log` in append mode
- `GetLogWriter()` - returns the raw log file writer (for MultiWriter)
- `Write(msg []byte)` - writes message with timestamp + dashes separator
- `Close()` - closes the file
- [x] 2. Wire into main.go
In `cmd/declpac/main.go` `run()`:
- Call `OpenLog()` at start
- `defer Close()` log
- [x] 3. Instrument pkg/pacman
Modify `pkg/pacman/pacman.go`:
All state-modifying functions use `state.Write()` instead of `state.GetLogWriter().Write()`:
```
// OLD
state.GetLogWriter().Write(output)
// NEW
state.Write(output) // auto-prepends timestamp
```
**Functions updated:**
- `SyncPackages()` - write output with timestamp
- `CleanupOrphans()` - write output with timestamp
- `MarkAllAsDeps()` - write operation name with timestamp before running
- `MarkAsExplicit()` - write operation name with timestamp before running
- `InstallAUR()` - write "Cloning ..." and "Building package..." with timestamps
- Error handling - `state.Write([]byte("error: ..."))` for all error paths
- [x] 4. Add io import
Add `io` to imports in pacman.go
- [x] 5. Test
Run a sync operation and verify log file created at `/var/log/declpac.log`
Loading…
Cancel
Save