Commit graph

4 commits

Author SHA1 Message Date
Rod Boev
ad7993bf15
fix(codex): stop pinning Codex memory MCP to one project db (#1269)
## Description

Stop `headroom wrap codex --memory` from pinning the global
`headroom_memory` MCP server to one absolute SQLite path. Today the
wrapper writes `--db <wrap-cwd>/.headroom/memory.db` into
`~/.codex/config.toml`, which makes later Codex sessions either reopen a
stale project-local DB or fail with `unable to open database file` when
that original path disappears. This change lets the MCP server use its
existing per-cwd default again, so each Codex session resolves
`.headroom/memory.db` from the active project instead of a serialized
past cwd. Closes #1147

The current Codex-memory config surface was shaped by
https://github.com/chopratejas/headroom/issues/462 and
https://github.com/chopratejas/headroom/issues/730; this PR keeps that
surface project-scoped again instead of globally pinning one DB.

## Type of Change

- [x] Bug fix (non-breaking change that fixes an issue)
- [ ] New feature (non-breaking change that adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Documentation update
- [ ] Performance improvement
- [ ] Code refactoring (no functional changes)

## Changes Made

- remove the injected `--db` argument from the global `headroom_memory`
Codex MCP block while keeping `--user` intact
- preserve the wrap-time local `.headroom/memory.db` setup and
Claude-memory import path for the current project
- treat only wrap-owned Codex markers as snapshot-suppression and
unwrap-cleanup signals, so pre-existing named MCP blocks still back up
and restore
- log a startup diagnostic from `headroom.memory.mcp_server` that
records the configured DB path, config source, cwd/project root,
resolved storage scope, path existence/readability, and whether the path
was static or cwd-derived
- add a shared MCP SDK test stub so both the memory MCP and CCR MCP test
surfaces still run in CI when `mcp` is absent
- make the shared MCP stub re-import target modules under the stubbed
dependency set and restore any pre-existing target module object plus
dotted parent-package attribute state after cleanup
- add focused regressions and guard coverage for the persisted Codex
config shape, named-MCP marker backup and restore, the no-backup
memory-only unwrap path, the wrap-memory-then-unwrap cleanup path, the
failed-wrap memory-only cleanup path, the startup-diagnostic path
classification, the shared-store CCR retrieval path, and the shared MCP
stub import lifecycle
- add a `CHANGELOG.md` entry for the user-visible Codex memory scoping
fix

## Testing

- [x] Unit tests pass (`pytest`)
- [x] Linting passes (`ruff check .`)
- [ ] Type checking passes (`uv run mypy headroom`)
- [x] New tests added for new functionality
- [ ] Manual testing performed

### Test Output

```text
uv run pytest tests/test_ccr_mcp_server.py tests/test_memory/test_mcp_server.py tests/test_cli/test_wrap_codex.py tests/test_mcp_stub.py
======================== 78 passed, 1 warning in 5.96s ========================
Pytest warning:
PytestConfigWarning: Unknown config option: asyncio_mode
Pytest post-success atexit noise:
PermissionError: [WinError 5] Access is denied: 'C:\Users\Rod\AppData\Local\Temp\pytest-of-Rod\pytest-current'

uv run ruff check headroom/cli/wrap.py headroom/memory/mcp_server.py tests/_mcp_stub.py tests/test_ccr_mcp_server.py tests/test_cli/test_wrap_codex.py tests/test_mcp_stub.py tests/test_memory/test_mcp_server.py
All checks passed!

uv run ruff format headroom/cli/wrap.py headroom/memory/mcp_server.py tests/_mcp_stub.py tests/test_ccr_mcp_server.py tests/test_cli/test_wrap_codex.py tests/test_mcp_stub.py tests/test_memory/test_mcp_server.py --check
7 files already formatted
```

## Real Behavior Proof

- Environment: isolated temp project directories, a temp Codex home, the
real `wrap codex` and `unwrap codex` CLI commands under pytest, a mocked
missing-`codex` launch path for the failed-wrap cleanup case, and shared
MCP-SDK stubs for the memory MCP and CCR MCP test modules so CI still
exercises those paths without a real `mcp` install.
- Exact command / steps: run `uv run pytest tests/test_ccr_mcp_server.py
tests/test_memory/test_mcp_server.py tests/test_cli/test_wrap_codex.py
tests/test_mcp_stub.py`; prove the persisted config shape with
`TestCodexMemoryMcpConfig::test_inject_omits_db_and_replaces_existing_memory_block`;
prove prepare-only wrap cleanup with
`test_wrap_codex_memory_prepare_only_unwrap_removes_memory_mcp_without_prior_config`;
prove failed-wrap cleanup with
`test_wrap_codex_memory_launch_failure_unwrap_cleans_memory_only_config`;
guard pre-existing named Codex MCP preservation with
`test_memory_only_wrap_restores_preexisting_named_mcp_block` and
`test_memory_only_wrap_without_backup_preserves_named_mcp_block`; prove
the startup diagnostic classifications with
`test_memory_mcp_startup_context_reports_dynamic_project_db` and
`test_memory_mcp_startup_context_reports_static_external_db`; prove the
shared-store CCR retrieval path with
`test_mcp_uses_shared_singleton_store` and
`test_mcp_retrieves_proxy_stored_content`; prove stub import cleanup
with `test_import_module_with_mcp_stub_imports_target_and_cleans_up`,
`test_import_module_with_mcp_stub_reimports_target_and_restores_originals`,
and
`test_import_module_with_mcp_stub_cleans_up_dotted_target_attribute`.
- Observed result: the persisted global `headroom_memory` block now
keeps `--user` but omits `--db`; prepare-only memory setup still
bootstraps the current project's `.headroom/memory.db`; `headroom unwrap
codex --no-stop-proxy` now removes both the prepare-only generated
config and the failed-wrap memory-only config instead of leaving
`[mcp_servers.headroom_memory]` behind; pre-existing named Codex MCP
blocks remain restorable across both normal and no-backup memory-only
unwrap paths because only wrap-owned markers suppress backups or trigger
named-block cleanup; the memory MCP server now logs whether its DB path
came from the cwd default or an explicit static path, along with the
resolved path and scope it will open; CI can exercise both MCP test
modules even when the `mcp` package is absent from the shard
environment, and the shared stub now re-imports target modules under the
stubbed SDK while restoring both dependency and dotted parent-package
target-module import state after cleanup.
- Not tested: full end-to-end interactive Codex CLI launch.

## Review Readiness

- [x] I have performed a self-review
- [x] This PR is ready for human review

## Checklist

- [x] My code follows the project's style guidelines
- [x] I have performed a self-review of my code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [x] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [x] I have updated the CHANGELOG.md if applicable

## Additional Notes

The code change stays narrowly scoped to Codex memory config
persistence, cleanup, and startup observability. It does not widen into
larger memory-routing redesign or startup-failure recovery logic.
2026-06-23 07:49:07 -05:00
Dashsoap
4e9d7df0ec
ci: align codecov-action to v5 in native e2e workflows (#978)
## Description

Bump `codecov/codecov-action` from `@v4` to `@v5` in the two native e2e
workflows, and rename the `file:` input to `files:` to match the v5 API.
The main `ci.yml` already uses `@v5` with `files:`; this aligns the
remaining Codecov uploads.

Follow-up to #968.

## Type of Change

- [x] Code refactoring (no functional changes)

## Changes Made

- `.github/workflows/install-native-e2e.yml`:
`codecov/codecov-action@v4` to `@v5`, and `file:` to `files:`.
- `.github/workflows/wrap-native-e2e.yml`: `codecov/codecov-action@v4`
to `@v5`, and `file:` to `files:`.
- All three Codecov uploads now use `@v5` with the `files:` input.

## Testing

- [x] Manual testing performed

### Test Output

```text
python -c "import yaml; [yaml.safe_load(open(f, encoding='utf-8')) for f in ['.github/workflows/install-native-e2e.yml','.github/workflows/wrap-native-e2e.yml','.github/workflows/ci.yml']]; print('all workflows parse as valid YAML')"
all workflows parse as valid YAML

rg -n "codecov/codecov-action@|^\s+file:|^\s+files:" .github/workflows/install-native-e2e.yml .github/workflows/wrap-native-e2e.yml .github/workflows/ci.yml
.github/workflows/install-native-e2e.yml:61:        uses: codecov/codecov-action@v5
.github/workflows/install-native-e2e.yml:63:          files: ./coverage-install-native.xml
.github/workflows/wrap-native-e2e.yml:66:        uses: codecov/codecov-action@v5
.github/workflows/wrap-native-e2e.yml:68:          files: ./coverage-wrap-native.xml
.github/workflows/ci.yml:209:        uses: codecov/codecov-action@v5
.github/workflows/ci.yml:211:          files: coverage-${{ matrix.shard }}.xml

git diff --check upstream/main...HEAD
# no output
```

## Real Behavior Proof

- Environment: local Windows 11 checkout, Python 3.13.13 with PyYAML,
ripgrep.
- Exact command / steps: rebased onto current `main`, parsed the three
workflow YAML files, confirmed all Codecov action references use `@v5`,
confirmed upload inputs use `files:`, and checked the diff for
whitespace errors.
- Observed result: workflow YAML parses; native e2e and CI Codecov
upload steps are aligned on `@v5`/`files:`; no whitespace errors.
- Not tested: live Codecov upload, because it requires Actions secrets
and GitHub-hosted runners. The PR workflows exercise the changed steps.

## Review Readiness

- [x] I have performed a self-review
- [x] This PR is ready for human review
2026-06-16 16:05:34 -05:00
Tejas Chopra
01fdedc630
ci: pass CODECOV_TOKEN to coverage uploads (fixes red test shards) (#968)
## Description

Every `test (N)` shard has been failing on all PRs and on pushes to
`main`, even though all tests pass. Root cause: **Codecov retired
tokenless uploads.** Without a token, the upload is rejected with `Token
required because branch is protected`, and `ci.yml` had
`fail_ci_if_error: true` with no token — so the rejected upload failed
the whole shard.

This passes `CODECOV_TOKEN` to the coverage-upload steps so uploads
authenticate again.

Closes #

## Type of Change

- [x] Bug fix (non-breaking change that fixes an issue)
- [ ] New feature (non-breaking change that adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Documentation update
- [ ] Performance improvement
- [ ] Code refactoring (no functional changes)

## Changes Made

- `ci.yml`: add `token: ${{ secrets.CODECOV_TOKEN }}` to the shard
upload step; guard `fail_ci_if_error` so it stays enforced on same-repo
PRs and pushes but relaxes on fork PRs (which cannot read repo secrets).
- `wrap-native-e2e.yml`, `install-native-e2e.yml`: add the same token so
their coverage uploads authenticate too (these were silently dropping
coverage; already non-fatal).

## Testing

- [x] Unit tests pass (`pytest`)
- [x] Linting passes (`ruff check .`)
- [ ] Type checking passes (`mypy headroom`)
- [x] New tests added for new functionality
- [x] Manual testing performed

### Test Output

```text
$ python -c "import yaml; [yaml.safe_load(open(f)) for f in [
    '.github/workflows/ci.yml',
    '.github/workflows/wrap-native-e2e.yml',
    '.github/workflows/install-native-e2e.yml']]"
OK ci.yml
OK wrap-native-e2e.yml
OK install-native-e2e.yml

This PR's own `test (N)` shards are the real test: with CODECOV_TOKEN set,
they should upload successfully and go green.
```

## Real Behavior Proof

- Environment: GitHub Actions, `codecov/codecov-action@v5` (ci.yml) /
`@v4` (e2e); repo is public; `CODECOV_TOKEN` repo secret set by the
maintainer.
- Exact command / steps: open this PR → observe the `test (1..4)` shards
upload coverage with the token instead of being rejected.
- Observed result: prior runs showed `1592 passed` then `Token required
because branch is protected` → shard failed; main's own push CI was red
for the same reason. With the token referenced, the upload
authenticates.
- Not tested: fork-PR path (no secret) — by design it now relaxes
`fail_ci_if_error` so the tokenless rejection is non-fatal there.

## Review Readiness

- [x] I have performed a self-review
- [x] This PR is ready for human review

## Checklist

- [x] My code follows the project's style guidelines
- [x] I have performed a self-review of my code
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] I have updated the CHANGELOG.md if applicable

## Additional Notes

Requires the `CODECOV_TOKEN` repository secret (GitHub → Settings →
Secrets and variables → Actions). No code/CHANGELOG change. Separate
from the output-token-reduction feature PR #965.
2026-06-13 23:35:30 -07:00
Copilot
b716c8c2ee
fix(ci): correct comments, timeouts, and pip reliability in native e2e workflows (#878)
Review feedback on PR #837 identified several issues in the newly added
`wrap-native-e2e.yml` and `install-native-e2e.yml` workflows.

## Changes

**`wrap-native-e2e.yml`**
- Header comment claimed "linux / macos / windows" coverage — Windows is
matrix-excluded; updated to reflect actual runners and note Windows is
pending CRT fix
- Removed Windows-specific wording ("Windows path handling") from the
workflow description; made OS-agnostic
- `timeout-minutes`: `15` → `25` to match `init-native-e2e.yml` and
avoid maturin build flakes on macOS

**Both `wrap-native-e2e.yml` and `install-native-e2e.yml`**
- pip install made more resilient on macOS runners, matching the pattern
already used in `ci.yml`:
```yaml
- name: Install pytest
  shell: bash
  run: |
    python -m pip install --upgrade pip
    python -m pip install --retries 10 --timeout 60 pytest pytest-cov
```
- `timeout-minutes`: `15` → `25` in `install-native-e2e.yml` for the
same reason

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: JD Davis <mxjerrett@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-06-11 21:02:05 -07:00