222 lines
11 KiB
Markdown
222 lines
11 KiB
Markdown
# Implementation plan: OpenCode Toolkit
|
|
|
|
## Objective
|
|
|
|
Create an independent, small OpenCode V2-native project using selected and
|
|
reviewed ECC skills, agent prompts, and workflows. The ECC fork remains a source
|
|
of reference, not a runtime dependency. The new package must be reproducible,
|
|
installable in a project, testable without a model provider, and explicit about
|
|
unverified behavior.
|
|
|
|
## Starting assumptions and decisions
|
|
|
|
- ECC source: `https://github.com/sargatxet/ECC`, commit
|
|
`ef648e01899ba3e8dc6371642deaaf64b4477775`, version 2.2.3, MIT.
|
|
- Runtime baseline: OpenCode 2.0.24, `@opencode/plugin` 2.0.24, Node.js
|
|
24.21.0 in the development environment; declared minimum Node.js 20.
|
|
- Scope: OpenCode V2 only for the initial release. No attempt to retain ECC's
|
|
Claude Code, Codex, or other harness installers.
|
|
- Distribution: one ESM package; project-local install first. Global/XDG
|
|
installation and npm publication are deferred.
|
|
- Provider and model selection remains user-owned. No credentials, model
|
|
defaults, or paid model calls are configured by this package.
|
|
- Content is selected and adapted, not copied wholesale. Preserve upstream
|
|
license text and per-file provenance.
|
|
|
|
## Initial scope
|
|
|
|
### Included
|
|
|
|
- Skills: `coding-standards`, `security-review`, `tdd-workflow`.
|
|
- Agents: planner, code reviewer, security reviewer.
|
|
- V2 plugin: `toolkit_project_status`, a read-only wrapper over OpenCode's VCS
|
|
context and status APIs.
|
|
- Project installer/uninstaller: copy the selected content, register the npm
|
|
plugin with a JSONC-preserving edit, track file ownership with SHA-256, reject
|
|
collisions and symlinks, and preserve modified files during uninstall.
|
|
- Unit tests, installer integration tests, coverage threshold, provenance,
|
|
operating documentation, FIXME and TODO tracking.
|
|
|
|
### Explicitly deferred
|
|
|
|
- ECC's V1 hook runtime, Claude-specific session discovery, continuous-learning
|
|
storage, instincts, memory vault, shell automation profiles, global installs,
|
|
multiple OpenCode config-layer reconciliation, npm publication, and
|
|
provider-backed E2E flows.
|
|
- Duplicating native OpenCode file, shell, search, delegation, and VCS tools when
|
|
a native API already satisfies the use case.
|
|
|
|
## Architecture
|
|
|
|
- `src/plugin.ts`: stable V2 `Plugin.define` entry point and namespaced tool.
|
|
- `src/installer/config.ts`: JSONC-safe plugin registration edits.
|
|
- `src/installer/project.ts`: project-local file staging, ownership manifest,
|
|
safe update, and conservative uninstall.
|
|
- `src/cli.ts`: `install` and `uninstall` commands.
|
|
- `content/skills/` and `content/agents/`: versioned content distributed with
|
|
the package.
|
|
- `test/`: Node test-runner tests for plugin API shape, config edits, install
|
|
idempotency, collisions, local edits, and symlink protection.
|
|
- `docs/PROVENANCE.md`: origin, commit, license, adaptations, and hashes.
|
|
|
|
## Work phases and acceptance criteria
|
|
|
|
### Phase 0 — Establish project and contract (complete)
|
|
|
|
- Create the separate repository without changing the ECC fork.
|
|
- Pin OpenCode SDK version 2.0.24 and establish a test/build baseline.
|
|
- Record package identity as provisional and document scope.
|
|
|
|
**Acceptance:** independent project builds; ECC source remains unchanged.
|
|
|
|
### Phase 1 — Select and import content (initial subset complete)
|
|
|
|
- Review each workflow for Claude-only paths, unavailable scripts, models, and
|
|
cross-references.
|
|
- Include supporting files, adapt frontmatter to native OpenCode agent format,
|
|
and record source SHA and file hashes.
|
|
- Confirm IDs are unique and are installed under `toolkit-*` names.
|
|
|
|
**Acceptance:** OpenCode discovers installed skills and agents; resources are
|
|
present; imported files have provenance and license attribution.
|
|
|
|
### Phase 2 — Prove V2 runtime (complete)
|
|
|
|
- Use `Plugin.define({ id, setup(ctx) })`, V2 transforms and documented VCS APIs.
|
|
- Avoid the V1 plugin callback, V1 event names, and module-global session state.
|
|
- Verify namespaced tool registration and output through contract tests.
|
|
- Test loading and tool execution under an actual OpenCode 2.0.24 runtime.
|
|
|
|
**Acceptance:** installed package loads and the tool runs in a real OpenCode
|
|
session. Verified using a local mock OpenAI-compatible endpoint; no external
|
|
provider call was made.
|
|
|
|
### Phase 3 — Implement project installer (initial behavior complete)
|
|
|
|
- Preflight all content and paths; reject collisions, non-regular files, and
|
|
symlinked install paths.
|
|
- Refuse simultaneous direct and `.opencode/` project config files until their
|
|
V2 merge behavior is handled safely.
|
|
- Preserve existing JSONC and unrelated settings.
|
|
- Write an ownership manifest with hashes; allow repeat installation only when
|
|
previously managed files remain unchanged.
|
|
- On updates, remove stale package-owned files only when their stored hash still
|
|
matches; keep locally edited stale files tracked and report them.
|
|
- Remove only package-owned, unmodified assets and a plugin entry the installer
|
|
originally added.
|
|
- Test clean install, re-run, collision, user-edited files, malformed config,
|
|
and symlink cases.
|
|
|
|
**Acceptance:** project install is idempotent; user files are not overwritten;
|
|
uninstall preserves locally modified content.
|
|
|
|
### Phase 4 — Validate distribution artifact (complete)
|
|
|
|
- Build and pack the real package.
|
|
- Install its tarball into a clean project outside this repository.
|
|
- Check all imports/content/license files and load the plugin with OpenCode.
|
|
- Verify behavior in a project with pre-existing config and skills.
|
|
|
|
**Progress:** package tarball installs outside the checkout; the CLI is
|
|
idempotent and OpenCode discovers the three packaged agents. Runtime testing
|
|
showed that the old npm-name entry caused a registry 404 and that the namespaced
|
|
tool needed Code Mode enabled. Both were corrected and the packaged plugin and
|
|
tool were verified in a local mock-provider session. The actual `0.1.0` tarball
|
|
was also installed into an isolated project containing a pre-existing JSONC
|
|
config, unrelated plugin, and user-owned skill. Assertions confirmed that
|
|
installation preserved those resources and installed all three toolkit skills,
|
|
the package entry point, and license files; a second install made no changes.
|
|
After locally editing an installed toolkit skill, uninstall removed the
|
|
unmodified package-owned assets and only the toolkit plugin entry, while
|
|
preserving the edited skill, user config, unrelated plugin, and user-owned skill.
|
|
The package was installed from the tarball with its declared dependencies, not
|
|
from a checkout path or symlink. `npm run typecheck`, all 16 tests,
|
|
`npm run test:coverage` (87.4% lines, 95.23% functions), and `npm pack --dry-run`
|
|
also passed. The temporary fixture and assertions were under `/tmp/opencode`;
|
|
provider-backed agent delegation and skill behavior remain unverified.
|
|
|
|
**Acceptance:** no checkout symlink or development dependency is needed at
|
|
runtime; config collisions are handled or reported before writes; the V2 plugin
|
|
and its custom tool are confirmed active.
|
|
|
|
### Phase 5 — Document and release (repository pre-release published)
|
|
|
|
- Document scope, installation, update/uninstall, compatibility, provenance,
|
|
and known limitations.
|
|
- Run deterministic checks and security review before release.
|
|
- Confirm package/repository names and get explicit approval before publishing.
|
|
|
|
**Progress:** README now documents installing directly from the repository's
|
|
pre-release tarball, as well as updating and uninstalling. A manual pre-release
|
|
review of installer paths, ownership, JSONC edits, symlinks, and failure behavior
|
|
found no release blocker for trusted project-local use; filesystem and
|
|
provider-backed limitations are recorded in [`SECURITY-REVIEW.md`](SECURITY-REVIEW.md).
|
|
Typecheck, all 16 tests, coverage (87.4% lines), and package build passed. The
|
|
`v0.1.0-rc.1` pre-release and SHA-256 sidecar are published. A clean project
|
|
installed the package using the public release URL, and the downloaded tarball
|
|
matched its recorded SHA-256.
|
|
|
|
**Acceptance:** another user can install from documented instructions and
|
|
verify the deterministic behavior without credentials.
|
|
|
|
### Phase 6 — Optional memory and learning features (memory milestone implemented)
|
|
|
|
- Design persistent memory and session-learning APIs separately.
|
|
- Prefer V2 public APIs over assumptions about OpenCode's storage layout.
|
|
- Add opt-in, scope controls, retention behavior, and isolation tests.
|
|
|
|
**Progress:** explicit memory tools now use the V2 plugin storage API. They are
|
|
disabled by default, session-scoped by project/session, and support separately
|
|
opted-in canonical-project scope, explicit retrieval/deletion, and configurable
|
|
expiry. Deterministic tests cover scope isolation and expiry. Live profile
|
|
storage persistence and user-profile isolation, along with provider-backed
|
|
learning proposals, remain unverified; automatic prompt/session capture is
|
|
deliberately not implemented.
|
|
|
|
**Acceptance:** explicit consent and tests prove project/session/user data
|
|
cannot be mixed or silently uploaded. This phase remains in progress until
|
|
storage behavior is verified in OpenCode 2.0.24 and learning proposals receive a
|
|
separate design and validation.
|
|
|
|
## Verification strategy
|
|
|
|
### Deterministic, no-model checks
|
|
|
|
- `npm run typecheck`, `npm test`, coverage threshold, package dry-run.
|
|
- Plugin API contract tests using V2 types and V2-shaped context.
|
|
- Installer tests using isolated temporary projects.
|
|
- Real OpenCode config parse and plugin load smoke test.
|
|
- Tarball install test outside the repository.
|
|
|
|
### Provider-backed checks
|
|
|
|
- Load the three workflows; delegate to planner/reviewer; invoke skills; verify
|
|
model-visible permissions and agent behavior.
|
|
- These tests need a configured provider and may incur cost. They require an
|
|
explicit budget and must not be represented by mocks as passed.
|
|
|
|
## Risks and mitigations
|
|
|
|
- **OpenCode config precedence:** direct and `.opencode/` config files have
|
|
layered precedence. Test the actual 2.0.24 behavior before supporting complex
|
|
multi-file layouts; fail safely rather than silently hide user plugins.
|
|
- **Package dependency resolution:** tests against the source checkout can hide
|
|
missing package files. Validate an installed tarball.
|
|
- **Content drift:** selective copying creates manual sync work. Compare source
|
|
SHAs and hashes during updates; never auto-sync all of ECC.
|
|
- **Session data leaks:** do not use module-global mutable maps for session
|
|
state; add isolation tests before adding tracking or memory.
|
|
- **Permission weakening:** do not inherit ECC's auto-approval behavior without
|
|
an explicit V2 permission design and security review.
|
|
- **Uninstall partial failures:** file operations can fail mid-run; preserve the
|
|
manifest and report recovery instructions. Transactional rollback remains a
|
|
follow-up.
|
|
|
|
## Change management
|
|
|
|
For each ECC refresh, compare the pinned upstream revision, select changes
|
|
component-by-component, inspect dependencies and licensing, update hashes, and
|
|
run the full deterministic and runtime checks. Maintain a compatibility matrix
|
|
for OpenCode versions actually tested. Do not publish or push without explicit
|
|
authorization.
|