Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 33 additions & 11 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,20 @@ opencode-acp/
│ │
│ └── update.ts # Auto-update check and notification
├── devlog/ # Development iteration logs (templates + per-iteration entries)
│ ├── README.md # Usage guide and naming conventions
│ ├── REQ.template.md # Requirement template
│ ├── WORKLOG.template.md # Worklog template
│ ├── DESIGN.template.md # Design document template
│ └── YYYY-MM-DD_short-title/ # One folder per iteration (REQ.md + WORKLOG.md minimum)
├── scripts/ # Utility scripts
│ ├── print.ts # Print DCP info
│ ├── verify-package.mjs # Package verification before publish
│ ├── README.md # Scripts documentation
│ └── ... # CLI tools for session inspection
├── tests/ # Test files — 343 tests across 22 files
├── tests/ # Test files — 350 tests across 22 files
├── lib/config-validation.ts # Pure validation logic (extracted from config.ts for testability)
├── dcp.schema.json # JSON schema for config validation
├── tsconfig.json # TypeScript config
Expand Down Expand Up @@ -344,7 +351,7 @@ npm run check:package # Build + verify
**Test directory**: Flat `tests/` structure — all test files in `tests/*.test.ts`. No subdirectories.
The project has ~20 source files and 15-25 test files; flat structure is sufficient.

No CI/CD is configured. Tests run locally.
CI is configured via GitHub Actions (PR #2): typecheck + test + build on Node 22/24 matrix.

**Baseline**: Tag `v1.0.1-test-baseline` — 95 tests, initial state before ACP test fixes.

Expand All @@ -358,7 +365,7 @@ No CI/CD is configured. Tests run locally.
| **Functional** | `compress-search.test.ts`, `compress-state.test.ts`, `message-ids.test.ts` | 77 | Compress pipeline with mock data |
| **E2E** | `e2e-message-transform.test.ts`, `e2e-blocks-nudges.test.ts` | 21 | Full message-transform pipeline |

**Total: 343 tests, 0 failures** (as of commit `7268202` + review fixes)
**Total: 350 tests, 0 failures** (as of commit `5e54496`)

**Test review requirement**: All new and modified test files MUST undergo independent review by at least 2 separate agents before commit. See Section 5.4.

Expand Down Expand Up @@ -473,14 +480,29 @@ For reference when modifying code — these bugs were real and the fixes are loa

All changes MUST follow this workflow:

1. Create a feature branch from `master`
2. Implement changes
3. Ensure `npm run build` and `npm run typecheck` pass
4. Ensure all tests pass: `npm run test`
5. Commit with descriptive messages
6. Push branch and create a GitHub PR
7. Obtain **dual-agent review** (Sections 5.3 + 5.4) on the PR
8. Merge PR after both reviews pass
1. Create a feature branch from `master` (naming: `YYYY-MM-DD_short-title`)
2. Create devlog entry: `devlog/{YYYY-MM-DD_short-title}/` with `REQ.md` (see Section 5.1.2)
3. Implement changes
4. Ensure `npm run build` and `npm run typecheck` pass
5. Ensure all tests pass: `npm run test`
6. Commit with descriptive messages (include devlog files)
7. Push branch and create a GitHub PR
8. Obtain **dual-agent review** (Sections 5.3 + 5.4) on the PR
9. Merge PR after both reviews pass

### 5.1.2 Devlog Requirement (MANDATORY)

Every PR MUST have a corresponding devlog entry in `devlog/{YYYY-MM-DD_short-title}/`.

**Rules:**
- The folder name MUST match the branch name
- `REQ.md` and `WORKLOG.md` are the required minimum
- `DESIGN.md` is required for any change affecting architecture, data flow, or module boundaries
- `REQ.md` should be filled **BEFORE** implementation (functions as a ticket)
- `WORKLOG.md` should be updated **DURING** and **AFTER** implementation
- Devlog files are committed alongside code changes — not as a separate afterthought

See `devlog/README.md` for templates and naming conventions.

### 5.2 After Making Changes

Expand Down
59 changes: 59 additions & 0 deletions devlog/2026-05-15_acp-rebrand/REQ.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# REQ - DCP → ACP Rebrand

- Task ID: `2026-05-15_acp-rebrand`
- Home Repo: `opencode-acp`
- Created: 2026-05-15
- Status: Done
- Priority: P0
- Owner: ranxianglei
- References: Forked from `@tarquinen/opencode-dcp` v3.1.11

## 1. Background & Problem Statement

- **Context**: Forked opencode-dcp (Dynamic Context Pruning) with 35 bug fixes applied. The fork needs its own identity separate from upstream DCP.
- **Current behavior (symptom)**: All user-visible text, commands, storage paths, and config files reference "DCP" — the upstream project name.
- **Expected behavior**: Full rebrand to "ACP" (Active Context Pruning) across all user-facing surfaces while maintaining backward compatibility with existing DCP installations.
- **Impact**: Without rebranding, users cannot distinguish ACP from upstream DCP, and npm package name conflicts prevent independent publishing.

## 2. Reproduction (if applicable)

- N/A — this is a branding/packaging change, not a bug.

## 3. Constraints & Non-Goals

- **Constraints**:
- Backward compatibility: Existing `/dcp` command must continue to work
- Storage migration: `plugin/dcp/` state must be auto-migrated to `plugin/acp/`
- Config migration: `dcp.jsonc` must be auto-migrated to `acp.jsonc`
- Internal code tags (`dcp-message-id`, `dcp-system-reminder`) must NOT change — they appear in persisted state and LLM interactions
- **Non-Goals**:
- Changing internal XML tags or regex variable names (backward compat required)
- Changing the API or behavior of the plugin

## 4. Acceptance Criteria (must be testable)

- **Correctness**:
- [x] `/acp` command works and shows ACP branding
- [x] `/dcp` command still works as backward-compatible alias
- [x] Storage auto-migrates from `plugin/dcp/` to `plugin/acp/`
- [x] Config auto-migrates from `dcp.jsonc` to `acp.jsonc`
- [x] All user-visible text says "ACP" not "DCP"
- **Performance / Stability**:
- [x] No performance regression from migration logic
- **Regression**:
- [x] Existing tests pass after rename
- [x] `npm run build` succeeds
- [x] `npm publish` succeeds (resolved 3 TS errors blocking publish)

## 5. Proposed Approach (optional)

- **Affected modules & entry files**:
- `lib/commands/` — rename command registration
- `lib/config.ts` — config migration logic
- `lib/state/persistence.ts` — storage migration
- `lib/messages/inject/inject.ts` — context usage text
- `lib/prompts/` — all prompt templates
- `README.md` — full rewrite with migration guide
- `package.json` — npm package rename
- **Risks**: Breaking existing DCP installations if migration fails silently
- **Rollback strategy**: Revert to DCP naming; `/dcp` command remains functional as fallback
80 changes: 80 additions & 0 deletions devlog/2026-05-15_acp-rebrand/WORKLOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# WORKLOG - DCP → ACP Rebrand

- Task ID: `2026-05-15_acp-rebrand`
- Home Repo: `opencode-acp`
- Status: Done
- Updated: 2026-05-18

## 1. Summary

- **What was done**: Full DCP → ACP rebrand across all user-visible surfaces: command rename (`/dcp` → `/acp`), storage isolation (`plugin/dcp/` → `plugin/acp/`), config migration (`dcp.jsonc` → `acp.jsonc`), README rewrite, version bump to 1.0.1.
- **Why**: Fork needed its own identity separate from upstream DCP, with backward compatibility for existing installations.
- **Behavior / compatibility changes**: Yes — `/acp` is the primary command, `/dcp` is backward-compatible alias. Storage and config auto-migrate on first access.
- **Risk level**: Medium — migration logic must handle edge cases (existing dcp.jsonc, fallback paths)

## 2. Change Log

### Commits

| Commit | Description |
|--------|-------------|
| `1c4bcd5` | fix(Bug 35): suppress aging warnings below 50% context usage |
| `ca811c9` | rename: /dcp command → /acp (backward compatible, accepts both) |
| `25cc269` | docs: update README with Bug 35 and /acp command rename |
| `ba3db52` | rebrand: DCP → ACP in all user-visible injected text |
| `0ba85fa` | docs: full DCP→ACP rebrand in README + migration guide |
| `c5faeb8` | fix: add ACP full name and role definition to context usage injection |
| `ab72cd5` | feat: isolate storage from DCP - migrate plugin/dcp/ to plugin/acp/ |
| `a0bf36a` | fix: resolve 3 TS errors blocking npm publish + redesign README |
| `4fa2155` | feat: auto-migrate config and prompts from dcp to acp naming |
| `a6752a7` | fix: config migration runs even when dcp.jsonc fallback exists |
| `d9ed83c` | fix: use logger instead of console.log for storage migration |
| `9de007f` | chore: bump version to 1.0.1 |

### Key Files

- `lib/commands/index.ts` — Command registration: `/acp` primary, `/dcp` alias
- `lib/config.ts` — Three-layer config migration (global, config-dir, project)
- `lib/state/persistence.ts` — Storage migration: `plugin/dcp/` → `plugin/acp/`
- `lib/messages/inject/inject.ts` — Context usage injection text updated to ACP branding
- `lib/prompts/system.ts` — System prompt rebrand
- `README.md` — Full rewrite with migration guide, bug fix table, feature documentation
- `package.json` — Package name → `opencode-acp`, version → 1.0.1

## 3. Design & Implementation Notes

- **Entry point / key function**: `getConfig()` in `config.ts` handles auto-migration at config load time
- **Key configuration items**: Config search paths now look for `acp.jsonc` first, fall back to `dcp.jsonc`
- **Key logic explanation**: Migration is copy-based (not rename) so users can revert. If `acp.jsonc` doesn't exist but `dcp.jsonc` does, the file is copied. This runs at every config load, making it idempotent.

## 4. Testing & Verification

### Build & Test Commands

```sh
npm run build # Passes
npm run typecheck # Passes
npm run test # 95 tests (baseline), all pass
```

### Test Coverage

- Existing DCP test suite adapted for ACP naming (10 test fixes in `d5f1540`)
- No new tests added in this iteration

### Results

- **PASS**: Build succeeds, tests pass, npm publish succeeds
- **Key data**: Version 1.0.1 published to npm as `opencode-acp`

## 5. Risk Assessment & Rollback

- **Risk points**: Config migration edge case where both `acp.jsonc` and `dcp.jsonc` exist with different contents
- **Rollback method**: Revert to DCP naming; `/dcp` command remains functional
- **Compatibility notes**: Internal `dcp` tags preserved (Section 2.6 of AGENTS.md)

## 6. Lessons Learned

- What went well: Backward-compatible command alias (`/dcp` still works) prevented breakage
- What could be improved: Should have created AGENTS.md during this iteration (done in test iteration)
- Reusable conclusions: Copy-based migration (not rename) is safer for user data
54 changes: 54 additions & 0 deletions devlog/2026-05-16_test-infrastructure/REQ.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# REQ - Test Infrastructure

- Task ID: `2026-05-16_test-infrastructure`
- Home Repo: `opencode-acp`
- Created: 2026-05-16
- Status: Done
- Priority: P0
- Owner: ranxianglei
- References: Baseline tag `v1.0.1-test-baseline` (95 tests)

## 1. Background & Problem Statement

- **Context**: ACP had only the original DCP test suite (95 tests) with no coverage for most modules. Several bugs were found during the rebrand that tests would have caught.
- **Current behavior (symptom)**: 95 baseline tests covering only hooks permissions, compress tools, message priority, token counting, context limits, and update checks. No tests for state management, compression pipeline internals, message processing, or E2E flows.
- **Expected behavior**: Comprehensive test suite covering all major modules with multiple tiers (pure, mock, functional, E2E).
- **Impact**: Without tests, regressions are caught only by manual testing or in production. The `config.ts` file (~1125 lines) had untestable runtime dependencies that needed extraction.

## 2. Reproduction (if applicable)

- N/A — this is a new capability, not a bug fix.

## 3. Constraints & Non-Goals

- **Constraints**:
- Test runner: Node.js built-in (`node --import tsx --test`) — no Jest, no Vitest
- Flat `tests/` directory structure — no subdirectories
- Tests must import from actual source files, not reimplement logic locally
- **Non-Goals**:
- 100% line coverage — focus on behavioral coverage
- Testing private/internal functions that aren't exported
- Performance benchmarks

## 4. Acceptance Criteria (must be testable)

- **Correctness**:
- [x] 4 test tiers implemented: Tier 1 (pure), Tier 2 (mock), Functional, E2E
- [x] At least 300 tests total (target: 343)
- [x] All tests pass with 0 failures
- [x] Tests import from source, not local reimplementations
- **Performance / Stability**:
- [x] Full test suite runs in under 30 seconds
- **Regression**:
- [x] Bug found and fixed: `resetOnCompaction` didn't clear `messageIds`
- [x] `config-validation.ts` extracted from `config.ts` for testability

## 5. Proposed Approach (optional)

- **Affected modules & entry files**:
- `lib/config-validation.ts` — Extracted from `config.ts` (new file)
- `tests/` — 15 new test files
- `AGENTS.md` — Created with architecture documentation and test status
- `TESTING.md` — Created with test writing guide
- **Risks**: Extracting `config-validation.ts` could break imports if not done carefully
- **Rollback strategy**: Remove new test files; revert `config-validation.ts` extraction
79 changes: 79 additions & 0 deletions devlog/2026-05-16_test-infrastructure/WORKLOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# WORKLOG - Test Infrastructure

- Task ID: `2026-05-16_test-infrastructure`
- Home Repo: `opencode-acp`
- Status: Done
- Updated: 2026-05-19

## 1. Summary

- **What was done**: Built complete test suite from scratch — 95 → 343 tests across 4 tiers (Tier 1 pure, Tier 2 mock, Functional, E2E). Extracted `config-validation.ts` from `config.ts` for testability. Created `AGENTS.md` and `TESTING.md`.
- **Why**: Original DCP test suite had minimal coverage. Bugs during rebrand showed the need for comprehensive testing.
- **Behavior / compatibility changes**: Yes — `config-validation.ts` extracted as a new module. `resetOnCompaction()` now clears `messageIds`.
- **Risk level**: Low — new test files and one extracted module; no behavior changes to production code

## 2. Change Log

### Commits

| Commit | Description |
|--------|-------------|
| `d5f1540` | test: fix 10 failing tests for ACP rebrand and config changes |
| `d2bc632` | docs: add AGENTS.md with architecture, dev standards, and test status |
| `04105e2` | test: add TESTING.md + 83 Tier 1 unit tests (178 total, 0 failures) |
| `7471a1b` | test: add 68 Tier 2 mock-data unit tests (246 total, 0 failures) |
| `90b8c00` | test: add 77 functional tests for compress pipeline (322 total, 0 failures) |
| `7268202` | test: add 21 E2E tests for full message-transform pipeline (343 total, 0 failures) |
| `17aa4c1` | fix: resolve 4 critical test review issues + add mandatory test review to AGENTS.md |
| `b4529f9` | fix: restore purgeErrors.turns positive-number validation lost during extraction |

### Key Files

- `lib/config-validation.ts` — New: pure validation logic extracted from `config.ts`
- `tests/config-validation.test.ts` — 83 pure tests for config validation
- `tests/priority-classify.test.ts`, `tests/shape.test.ts`, `tests/query-pure.test.ts`, `tests/gc-truncate-pure.test.ts`, `tests/state-utils-pure.test.ts` — Tier 1 pure tests
- `tests/query-mock.test.ts`, `tests/gc-truncate-mock.test.ts`, `tests/strategies-dedup.test.ts`, `tests/strategies-purge-errors.test.ts` — Tier 2 mock tests
- `tests/compress-search.test.ts`, `tests/compress-state.test.ts`, `tests/message-ids.test.ts` — Functional tests
- `tests/e2e-message-transform.test.ts`, `tests/e2e-blocks-nudges.test.ts` — E2E tests
- `AGENTS.md` — New: comprehensive development specification
- `TESTING.md` — New: test writing guide

## 3. Design & Implementation Notes

- **Entry point / key function**: Tier 1 tests pure functions (no side effects). Tier 2 uses mock data. Functional tests exercise compress pipeline with factories. E2E tests run full message-transform pipeline.
- **Key configuration items**: `buildConfig()` factory used across tests to create valid `PluginConfig` objects
- **Key logic explanation**: `config-validation.ts` was extracted because `config.ts` has runtime dependencies (file I/O, SDK types) that made it untestable. The extraction separated pure validation logic into an importable module.

## 4. Testing & Verification

### Build & Test Commands

```sh
npm run build # Passes
npm run typecheck # Passes
npm run test # 343 tests, 0 failures
```

### Test Coverage

- New test files: 15
- Test count: 343 total, 343 pass, 0 fail
- Key scenarios verified: config validation, message priority, shape analysis, boundary search, block allocation, message ID mapping, full compress pipeline, nudge injection

### Results

- **PASS**: All 343 tests pass
- **Bug found during testing**: `resetOnCompaction()` didn't clear `messageIds` — fixed in `25cc269` (part of rebrand iteration)
- **Review findings**: 4 critical/important issues found by 3 independent reviewers and fixed in `17aa4c1` and `b4529f9`

## 5. Risk Assessment & Rollback

- **Risk points**: `config-validation.ts` extraction could introduce import path issues
- **Rollback method**: Revert commits `d5f1540` through `b4529f9`
- **Compatibility notes**: `purgeErrors.turns` validation was accidentally lost during extraction; restored in `b4529f9`

## 6. Lessons Learned

- What went well: 4-tier structure (pure → mock → functional → E2E) provides clear separation of concerns
- What could be improved: Should have extracted `config-validation.ts` before writing tests (would have avoided the lost validation bug)
- Reusable conclusions: `buildConfig()` factory pattern prevents missing required config fields in tests. Independent review caught issues that self-review missed.
Loading
Loading