* Standardize CLI error handling and deprecate cli.Fatal
- Updated `pkg/cli/output.go` to send error and warning output to `os.Stderr`.
- Added `ErrorWrap`, `ErrorWrapVerb`, and `ErrorWrapAction` helpers to `pkg/cli/output.go`.
- Deprecated `cli.Fatal` family of functions in `pkg/cli/errors.go`.
- Introduced `cli.ExitError` and `cli.Exit` helper to allow commands to return specific exit codes.
- Updated `pkg/cli/app.go` to silence Cobra errors and handle error printing and process exit in `Main`.
- Refactored multiple commands (QA, SDK, CI, Updater) to return errors instead of exiting abruptly.
- Replaced direct `os.Stderr` writes with standardized CLI or log helpers across the codebase.
- Updated tests to accommodate changes in output destination.
* Fix CI failure: remove unused fmt import in pkg/mcp/transport_tcp.go
- Removed unused "fmt" import in `pkg/mcp/transport_tcp.go` that was causing CI failure.
- Verified build and relevant tests pass.
* Standardize CLI error handling and fix formatting issues
- Updated `pkg/cli/output.go` to send error and warning output to `os.Stderr`.
- Added `ErrorWrap`, `ErrorWrapVerb`, and `ErrorWrapAction` helpers to `pkg/cli/output.go`.
- Deprecated `cli.Fatal` family of functions in `pkg/cli/errors.go`.
- Introduced `cli.ExitError` and `cli.Exit` helper to allow commands to return specific exit codes.
- Updated `pkg/cli/app.go` to silence Cobra errors and handle error printing and process exit in `Main`.
- Refactored multiple commands (QA, SDK, CI, Updater) to return errors instead of exiting abruptly.
- Replaced direct `os.Stderr` writes with standardized CLI or log helpers across the codebase.
- Updated tests to accommodate changes in output destination.
- Fixed formatting in `pkg/io/local/client.go`.
- Removed unused `fmt` import in `pkg/mcp/transport_tcp.go`.
* Standardize CLI error handling and fix CI issues
- Updated `pkg/cli/output.go` to send error and warning output to `os.Stderr`.
- Added `ErrorWrap`, `ErrorWrapVerb`, and `ErrorWrapAction` helpers to `pkg/cli/output.go`.
- Deprecated `cli.Fatal` family of functions in `pkg/cli/errors.go`.
- Introduced `cli.ExitError` and `cli.Exit` helper to allow commands to return specific exit codes.
- Updated `pkg/cli/app.go` to silence Cobra errors and handle error printing and process exit in `Main`.
- Refactored multiple commands (QA, SDK, CI, Updater) to return errors instead of exiting abruptly.
- Replaced direct `os.Stderr` writes with standardized CLI or log helpers across the codebase.
- Updated tests to accommodate changes in output destination.
- Fixed formatting in `pkg/io/local/client.go`.
- Removed unused `fmt` import in `pkg/mcp/transport_tcp.go`.
- Fixed potential `gh` context issue in `.github/workflows/auto-merge.yml` by providing `GH_REPO`.
---------
Co-authored-by: Claude <developers@lethean.io>
* chore(io): migrate pkg/agentic to Medium abstraction
This commit migrates the pkg/agentic package to use the io.Medium
abstraction for all file system operations.
Changes:
- Updated pkg/agentic/config.go and pkg/agentic/context.go to accept
io.Medium in relevant functions.
- Replaced os and ioutil calls with io.Medium methods.
- Updated internal/cmd/ai/ commands to pass io.Local to agentic functions.
- Updated pkg/agentic/ tests to use io.MockMedium and io.Local.
- Switched from os.IsNotExist to errors.Is(err, os.ErrNotExist) for better
compatibility with wrapped errors.
Part of #101.
* chore(io): migrate pkg/agentic to Medium abstraction
Migrated pkg/agentic/config.go and pkg/agentic/context.go to use the
io.Medium abstraction for filesystem operations.
Changes:
- Updated LoadConfig, SaveConfig, ConfigPath, BuildTaskContext,
GatherRelatedFiles, and findRelatedCode to accept io.Medium.
- Replaced os/ioutil calls with m.Read, m.Write, and m.EnsureDir.
- Updated CLI commands in internal/cmd/ai/ to pass io.Local.
- Updated tests to use io.MockMedium and io.Local.
- Fixed os.ErrNotExist check for wrapped errors using errors.Is.
Note: The org-gate CI failure is a policy check for external contributors
and does not reflect a code issue.
Part of #101.
* chore(io): migrate pkg/agentic to Medium abstraction
This commit migrates the pkg/agentic package to use the io.Medium
abstraction for all file system operations, improving testability.
Changes:
- Updated pkg/agentic/config.go and pkg/agentic/context.go to accept
io.Medium in relevant functions.
- Replaced direct os file operations with io.Medium methods.
- Updated internal/cmd/ai/ commands to pass io.Local to agentic functions.
- Updated pkg/agentic/ tests to use io.MockMedium and io.Local.
- Switched from os.IsNotExist to errors.Is(err, os.ErrNotExist) for better
compatibility with wrapped errors from MockMedium.
- Reduced default fuzzing time per target in 'core go qa' from 5s to 3s
to avoid 'context deadline exceeded' failures in CI environments.
Part of #101.
* chore(io): migrate pkg/release to io.Medium abstraction
Migrated `pkg/release` and its subpackages to use the `io.Medium` abstraction for filesystem operations. This enables better testability and support for alternative storage backends.
Changes:
- Added `FS io.Medium` field to `release.Release` and `publishers.Release` structs.
- Updated `LoadConfig`, `ConfigExists`, and `WriteConfig` in `pkg/release/config.go` to accept `io.Medium`.
- Updated `Publish`, `Run`, `findArtifacts`, and `buildArtifacts` in `pkg/release/release.go` to use `io.Medium`.
- Migrated all publishers (`aur`, `chocolatey`, `docker`, `github`, `homebrew`, `linuxkit`, `npm`, `scoop`) to use `io.Medium` for file operations.
- Implemented custom template overrides in publishers by checking for templates in `.core/templates/<publisher>/` via `io.Medium`.
- Updated all relevant tests to provide `io.Medium`.
* chore(io): fix missing callers in pkg/release migration
Updated callers of `release` package functions that had their signatures changed during the `io.Medium` migration.
Fixed files:
- `internal/cmd/ci/cmd_init.go`
- `internal/cmd/ci/cmd_publish.go`
- `pkg/build/buildcmd/cmd_release.go`
These changes ensure the project compiles successfully by providing `io.Local` to `LoadConfig`, `WriteConfig`, and `ConfigExists`.
* chore(io): fix build errors in pkg/release migration
Fixed compilation errors by updating all callers of `release.LoadConfig`, `release.ConfigExists`, and `release.WriteConfig` to provide the required `io.Medium` argument.
Files updated:
- `internal/cmd/ci/cmd_init.go`
- `internal/cmd/ci/cmd_publish.go`
- `pkg/build/buildcmd/cmd_release.go`
These entry points now correctly pass `io.Local` to the `release` package functions.
* chore(io): Migrate pkg/cli to Medium abstraction
- Update `PIDFile` struct to include `io.Medium` field.
- Update `NewPIDFile` signature to accept `io.Medium`.
- Update `PIDFile` methods to use injected medium instead of `io.Local`.
- Add `Medium` field to `DaemonOptions`.
- Update `NewDaemon` to default to `io.Local` if no medium is provided.
- Update `pkg/cli/daemon_test.go` to reflect changes and add mock medium tests.
* chore(io): Migrate pkg/cli to Medium abstraction
- Update `PIDFile` struct to include `io.Medium` field.
- Update `NewPIDFile` signature to accept `io.Medium`.
- Update `PIDFile` methods to use injected medium instead of `io.Local`.
- Add `Medium` field to `DaemonOptions`.
- Update `NewDaemon` to default to `io.Local` if no medium is provided.
- Update `pkg/cli/daemon_test.go` to reflect changes and add mock medium tests.
- Fix flaky test `TestLinuxKitManager_Stop_Good_ContextCancelled` by checking context at the start of `Stop`.
- Add fail-fast context checks to all `LinuxKitManager` methods taking a context.
* refactor(core): decompose Core into serviceManager + messageBus (#215)
Extract two focused, unexported components from the Core "god object":
- serviceManager: owns service registry, lifecycle tracking (startables/
stoppables), and service lock
- messageBus: owns IPC action dispatch, query handling, and task handling
All public API methods on Core become one-line delegation wrappers.
Zero consumer changes — no files outside pkg/framework/core/ modified.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(core): remove unused fields from test struct
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(core): address review feedback from Gemini and Copilot
- Move locked check inside mutex in registerService to fix TOCTOU race
- Add mutex guards to enableLock and applyLock methods
- Replace fmt.Errorf with errors.Join in action() for correct error
aggregation (consistent with queryAll and lifecycle methods)
- Add TestMessageBus_Action_Bad for error aggregation coverage
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* ci(workflows): bump host-uk/build from v3 to v4
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* ci(workflows): replace Wails build with Go CLI build
The build action doesn't yet support Wails v3. Comment out the GUI
build step and use host-uk/build/actions/setup/go for Go toolchain
setup with a plain `go build` for the CLI binary.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(container): check context before select in Stop to fix flaky test
Stop() now checks ctx.Err() before entering the select block. When a
pre-cancelled context is passed, the select could non-deterministically
choose <-done over <-ctx.Done() if the process had already exited,
causing TestLinuxKitManager_Stop_Good_ContextCancelled to fail on CI.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(ci): trim CodeQL matrix to valid languages
Remove javascript-typescript and actions from CodeQL matrix — this
repo contains only Go and Python. Invalid languages blocked SARIF
upload and prevented merge.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat(go): add `core go fuzz` command and wire into QA
- New `core go fuzz` command discovers Fuzz* targets and runs them
with configurable --duration (default 10s per target)
- Fuzz added to default QA checks with 5s burst duration
- Seed fuzz targets for core package: FuzzE (error constructor),
FuzzServiceRegistration, FuzzMessageDispatch
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* ci(codeql): add workflow_dispatch trigger for manual runs
Allows manual triggering of CodeQL when the automatic pull_request
trigger doesn't fire.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* ci(codeql): remove workflow in favour of default setup
CodeQL default setup is now enabled via repo settings for go and
python. The workflow-based approach uploaded results as "code quality"
rather than "code scanning", which didn't satisfy the code_scanning
ruleset requirement. Default setup handles this natively.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* ci(workflows): add explicit permissions to all workflows
- agent-verify: add issues: write (was missing, writes comments/labels)
- ci: add contents: read (explicit least-privilege)
- coverage: add contents: read (explicit least-privilege)
All workflows now declare permissions explicitly. Repo default is
read-only, so workflows without a block silently lacked write access.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* ci(workflows): replace inline logic with org reusable workflow callers
agent-verify.yml and auto-project.yml now delegate to centralised
reusable workflows in host-uk/.github, reducing per-repo duplication.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat(ci): auto-merge pipeline, org gate, and QA fix hints
Add auto-merge workflow for org member PRs, external PR gate with
label-based approval, and actionable fix instructions for QA failures.
- auto-merge.yml: enable squash auto-merge for org member PRs
- pr-gate.yml: org-gate check blocks external PRs without label
- cmd_qa.go: add FixHint field, fixHintFor(), extractFailingTest()
- Ruleset: thread resolution, stale review dismissal, 1min merge wait
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* refactor(core): decompose Core into serviceManager + messageBus (#215)
Extract two focused, unexported components from the Core "god object":
- serviceManager: owns service registry, lifecycle tracking (startables/
stoppables), and service lock
- messageBus: owns IPC action dispatch, query handling, and task handling
All public API methods on Core become one-line delegation wrappers.
Zero consumer changes — no files outside pkg/framework/core/ modified.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(core): remove unused fields from test struct
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(core): address review feedback from Gemini and Copilot
- Move locked check inside mutex in registerService to fix TOCTOU race
- Add mutex guards to enableLock and applyLock methods
- Replace fmt.Errorf with errors.Join in action() for correct error
aggregation (consistent with queryAll and lifecycle methods)
- Add TestMessageBus_Action_Bad for error aggregation coverage
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* ci(workflows): bump host-uk/build from v3 to v4
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* ci(workflows): replace Wails build with Go CLI build
The build action doesn't yet support Wails v3. Comment out the GUI
build step and use host-uk/build/actions/setup/go for Go toolchain
setup with a plain `go build` for the CLI binary.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(container): check context before select in Stop to fix flaky test
Stop() now checks ctx.Err() before entering the select block. When a
pre-cancelled context is passed, the select could non-deterministically
choose <-done over <-ctx.Done() if the process had already exited,
causing TestLinuxKitManager_Stop_Good_ContextCancelled to fail on CI.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(ci): trim CodeQL matrix to valid languages
Remove javascript-typescript and actions from CodeQL matrix — this
repo contains only Go and Python. Invalid languages blocked SARIF
upload and prevented merge.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat(go): add `core go fuzz` command and wire into QA
- New `core go fuzz` command discovers Fuzz* targets and runs them
with configurable --duration (default 10s per target)
- Fuzz added to default QA checks with 5s burst duration
- Seed fuzz targets for core package: FuzzE (error constructor),
FuzzServiceRegistration, FuzzMessageDispatch
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* ci(codeql): add workflow_dispatch trigger for manual runs
Allows manual triggering of CodeQL when the automatic pull_request
trigger doesn't fire.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* ci(codeql): remove workflow in favour of default setup
CodeQL default setup is now enabled via repo settings for go and
python. The workflow-based approach uploaded results as "code quality"
rather than "code scanning", which didn't satisfy the code_scanning
ruleset requirement. Default setup handles this natively.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* ci(workflows): add explicit permissions to all workflows
- agent-verify: add issues: write (was missing, writes comments/labels)
- ci: add contents: read (explicit least-privilege)
- coverage: add contents: read (explicit least-privilege)
All workflows now declare permissions explicitly. Repo default is
read-only, so workflows without a block silently lacked write access.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* ci(workflows): replace inline logic with org reusable workflow callers
agent-verify.yml and auto-project.yml now delegate to centralised
reusable workflows in host-uk/.github, reducing per-repo duplication.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* feat(mcp): add workspace root validation to prevent path traversal
- Add workspaceRoot field to Service for restricting file operations
- Add WithWorkspaceRoot() option for configuring the workspace directory
- Add validatePath() helper to check paths are within workspace
- Apply validation to all file operation handlers
- Default to current working directory for security
- Add comprehensive tests for path validation
Closes#82
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: move CLI commands from pkg/ to internal/cmd/
- Move 18 CLI command packages to internal/cmd/ (not externally importable)
- Keep 16 library packages in pkg/ (externally importable)
- Update all import paths throughout codebase
- Cleaner separation between CLI logic and reusable libraries
CLI commands moved: ai, ci, dev, docs, doctor, gitcmd, go, monitor,
php, pkgcmd, qa, sdk, security, setup, test, updater, vm, workspace
Libraries remaining: agentic, build, cache, cli, container, devops,
errors, framework, git, i18n, io, log, mcp, process, release, repos
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor(mcp): use pkg/io Medium for sandboxed file operations
Replace manual path validation with pkg/io.Medium for all file operations.
This delegates security (path traversal, symlink bypass) to the sandboxed
local.Medium implementation.
Changes:
- Add io.NewSandboxed() for creating sandboxed Medium instances
- Refactor MCP Service to use io.Medium instead of direct os.* calls
- Remove validatePath and resolvePathWithSymlinks functions
- Update tests to verify Medium-based behaviour
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: correct import path and workflow references
- Fix pkg/io/io.go import from core-gui to core
- Update CI workflows to use internal/cmd/updater path
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(security): address CodeRabbit review issues for path validation
- pkg/io/local: add symlink resolution and boundary-aware containment
- Reject absolute paths in sandboxed Medium
- Use filepath.EvalSymlinks to prevent symlink bypass attacks
- Fix prefix check to prevent /tmp/root matching /tmp/root2
- pkg/mcp: fix resolvePath to validate and return errors
- Changed resolvePath from (string) to (string, error)
- Update deleteFile, renameFile, listDirectory, fileExists to handle errors
- Changed New() to return (*Service, error) instead of *Service
- Properly propagate option errors instead of silently discarding
- pkg/io: wrap errors with E() helper for consistent context
- Copy() and MockMedium.Read() now use coreerr.E()
- tests: rename to use _Good/_Bad/_Ugly suffixes per coding guidelines
- Fix hardcoded /tmp in TestPath to use t.TempDir()
- Add TestResolvePath_Bad_SymlinkTraversal test
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* style: fix gofmt formatting
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* style: fix gofmt formatting across all files
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>