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
25 changes: 24 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,32 @@ Use `context_history` to navigate the edit DAG:
## Documentation Files

- Log all bugs in root `BUGS.md`, not per-package. Do not create `packages/*/BUGS.md`.
- Tracking docs (`PLAN.md`, `STATUS.md`, `WHAT_WE_DID.md`, `DO_NEXT.md`, `BUGS.md`) live at repo root.
- Tracking docs (`PLAN.md`, `STATUS.md`, `WHAT_WE_DID.md`, `DO_NEXT.md`, `BUGS.md`, `GAP_ANALYSIS.md`, `UPSTREAM_STATUS.md`) live at repo root.
- Do not create tracking/status markdown files inside `packages/`.

## Phase Methodology

Work follows the phased plan in `PLAN.md`. Each phase has exit criteria.

**Before starting a phase:**
1. Read `PLAN.md` to understand the phase scope and exit criteria
2. Read `GAP_ANALYSIS.md` to understand current state vs target
3. Read `DO_NEXT.md` for immediate actions
4. Read `BUGS.md` for any open issues that might affect the phase

**After completing a phase:**
1. Update `BUGS.md` — close fixed issues, add any new ones found
2. Update `STATUS.md` — refresh metrics (test count, error count, phase progress)
3. Update `WHAT_WE_DID.md` — add summary of work done
4. Update `GAP_ANALYSIS.md` — mark completed gaps, update current state
5. Update `DO_NEXT.md` — point to the next phase
6. Update `PLAN.md` — mark phase as complete, note PR number

**When starting a new session:**
1. Review `STATUS.md` and `DO_NEXT.md` to orient
2. Verify tests pass and tsgo has 0 errors before making changes
3. Follow the current phase in `PLAN.md`

## Type Checking

- Always run `bun typecheck` from package directories (e.g., `packages/opencode`), never `tsc` directly.
14 changes: 13 additions & 1 deletion BUGS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,19 @@ All bugs tracked here. Do not create per-package bug files.

---

## Open (0)
## Open — Security (5)

From upstream security audit. See [docs/SECURITY_AUDIT.md](docs/SECURITY_AUDIT.md) for full details.

| # | Issue | Sev | Location | Upstream | Notes |
| --- | ----- | ---- | -------- | -------- | ----- |
| S1 | `Filesystem.contains()` symlink bypass | Crit | `util/filesystem.ts` | [#8313](https://github.com/anomalyco/opencode/issues/8313) | Lexical check only, no `realpathSync()` |
| S2 | `exec()` command injection in github.ts | High | `cli/cmd/github.ts` | [#17350](https://github.com/anomalyco/opencode/issues/17350) | Use `spawn` with arg array |
| S3 | Untrusted `.opencode/` autoloading (MCP + plugins) | High | `mcp/`, `plugin/` | [#6361](https://github.com/anomalyco/opencode/issues/6361), [#7163](https://github.com/anomalyco/opencode/issues/7163) | No trust prompt |
| S4 | Server unauthenticated on non-loopback | Med | `server/server.ts` | [#10973](https://github.com/anomalyco/opencode/issues/10973) | Auth skips when no password |
| S5 | Read tool exposes .env files (ignores .gitignore) | Med | `tool/read.ts` | [#12196](https://github.com/anomalyco/opencode/issues/12196) | No sensitive file deny-list |

## Open — Bugs (0)

_No open bugs._

Expand Down
36 changes: 15 additions & 21 deletions DO_NEXT.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,23 @@
# Frankencode — Do Next

## Priority 1: Zod v3 → v4 Migration
Follow the phases in [PLAN.md](PLAN.md). Security first.

Single site: `server/routes/experimental.ts:91` uses `zodToJsonSchema(... as any)`. Replace `zod-to-json-schema` with Zod v4's built-in `z.toJSONSchema()`. Also audit `hono-openapi` resolver/validator calls for v3 compatibility.
## Immediate: Phase 1 — Security Fixes

See `PLAN.md` for full site list.
1. Fix S1: `Filesystem.contains()` — add `realpathSync()` in `src/util/filesystem.ts`
2. Fix S2: `exec()` → `spawn()` in `src/cli/cmd/github.ts`
3. Fix S3: workspace trust prompt for `.opencode/` MCP and plugins
4. Fix S4: server auth for non-loopback binding
5. Fix S5: sensitive file deny-list for read tool
6. Evaluate upstream security PRs: #10763, #10974, #14581

## Priority 2: Upstream Re-sync
## Then: Phase 2 — High-Priority Upstream Fixes

Upstream (`anomalyco/opencode`) has diverged since our last rebase. Effect-ification PRs are landing (7+ still open). Strategy: cherry-pick applicable fixes first, then full rebase.
Cherry-pick 8 commits from vouched contributors. See [PLAN.md](PLAN.md) Phase 2.

High-conflict areas: `session/prompt.ts`, `session/message-v2.ts`, `effect/`, `skill/skill.ts`.
## See Also

## Backlog: Testing

- [ ] Unit tests for CAS (store, get, dedup)
- [ ] Unit tests for filterEdited (hidden parts stripped)
- [ ] Unit tests for EditGraph (commit chain, log walk, checkout)
- [ ] Unit tests for SideThread CRUD
- [ ] Unit tests for ContextEdit validation (ownership, budget, recency)
- [ ] Unit tests for lifecycle sweeper (discardable auto-hide, ephemeral auto-externalize)
- [ ] TUI dialog tests (9 remaining: command, provider, session-rename, etc.)
- [ ] TUI interaction tests (dialog-select keyboard nav, prompt input, command palette)

## Backlog: Features

- [ ] TUI rendering of edit indicators (hidden/replaced/annotated parts)
- [ ] CAS garbage collection improvements (size limits, age-based cleanup)
- [PLAN.md](PLAN.md) — full 6-phase roadmap
- [GAP_ANALYSIS.md](GAP_ANALYSIS.md) — current vs target state per phase
- [BUGS.md](BUGS.md) — security issues S1-S5
- [UPSTREAM_STATUS.md](UPSTREAM_STATUS.md) — upstream commit/PR catalogue
96 changes: 82 additions & 14 deletions GAP_ANALYSIS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,89 @@

**Date:** 2026-03-21

## Goals — All Complete
## Current State → Target State by Phase

| Goal | Status |
|------|--------|
| Fix all bugs (B1-B52) | Done (51 fixed, 1 deferred) |
| Eliminate weak typing | Done (20 documented exceptions remain) |
| Architecture documentation | Done (8 docs in `docs/`) |
### Phase 1: Security Fixes

## Remaining Gaps
| Area | Current | Target |
|------|---------|--------|
| `Filesystem.contains()` | Lexical check only — symlinks escape project | `realpathSync()` + lexical check |
| `exec()` in github.ts | Shell string execution | `spawn()` with argument array |
| `.opencode/` autoloading | No trust prompt — MCP/plugins run on clone | Trust prompt before loading workspace configs |
| Server auth | Skips auth when no password set | Require password for non-loopback, or bind loopback only |
| Read tool | No .gitignore check — exposes .env | Sensitive file deny-list |
| Security bugs in BUGS.md | 5 open (S1-S5) | 0 open |

| Gap | Priority | Notes |
|-----|----------|-------|
| Zod v3→v4 migration | Medium | 1 site (`zodToJsonSchema`), see `PLAN.md` |
| Upstream re-sync | Medium | Upstream diverging, Effect PRs landing |
| Unit test coverage for Frankencode modules | Low | CAS, EditGraph, SideThread, ContextEdit, sweeper |
| TUI dialog/interaction tests | Low | 9 dialog + keyboard nav tests |
### Phase 2: High-Priority Upstream Fixes

See `DO_NEXT.md` for actionable items.
| Area | Current | Target |
|------|---------|--------|
| thinkingConfig | Set for all models | Only set for models with reasoning capability |
| SIGHUP handler | Missing | Restored (1-line fix from Dax) |
| Default timeout | Incorrect value | Fixed (2-line fix from Ariane Emory) |
| Event route processing | Synchronous | Queued to prevent backpressure |
| Forked prompt attachments | File parts lost | Preserved |
| Tagged error messages | Lost during processing | Preserved |
| Truncate permission | Import cycle | Broken cycle |
| Chunk timeout | Enabled by default | Disabled by default |

### Phase 3: Quality + OpenTUI

| Area | Current | Target |
|------|---------|--------|
| OpenTUI version | 0.1.88 | 0.1.90 |
| Agent/skill ordering | Non-deterministic | Stable ordering |
| apply_patch | Not in EDIT_TOOLS filter | Included |
| Provider.list() type | Loose | `Record<ProviderID, Info>` |
| Prompt schema debugging | No logs | Validation debug logs |

### Phase 4: Community Fixes + Features

| Area | Current | Target |
|------|---------|--------|
| Retry backoff | Unbounded exponential | Capped at 30s |
| 429 retry | Respects non-retryable flag | Retries transient 429s |
| Lone surrogates | 400 errors from providers | Stripped before sending |
| Empty content blocks | Sent to providers | Filtered out |
| LSP clients | Accumulate (memory leak) | Dead clients removed |
| Memory during prompting | Full scan | Lazy boundary scan + windowing |
| Subagent plan escape | Possible | Prevented |
| TUI permissions | Manual per-tool | Auto-accept mode option |

### Phase 5: Tests

| Area | Current | Target |
|------|---------|--------|
| filterEdited tests | 0 | Comprehensive (hidden, empty, synthetic placeholder) |
| ContextEdit validation | 0 | Ownership, budget, recency, privileged agents |
| TUI dialog tests | 0 | 9 dialogs covered |
| TUI interaction tests | 0 | Keyboard nav, prompt input, command palette |

### Phase 6: Effect Behavioral Analysis

| Area | Current | Target |
|------|---------|--------|
| Upstream Effect behaviors | Not analyzed | Each PR reviewed, valuable behaviors reimplemented |
| SkillService capabilities | Content cache only | + any new capabilities from upstream |
| FileTimeService | No semaphore | Evaluate if semaphore prevents races |
| VcsService | Our version | + HEAD filter fix if not already applied |

---

## Permanently Out of Scope

- Desktop/Electron app (never shipping)
- Bun→Node portability refactors (Bun-only target)
- Zen platform changes
- Web app UI (low priority, evaluate case-by-case)

---

## Cross-references

- [PLAN.md](PLAN.md) — phase details and exit criteria
- [BUGS.md](BUGS.md) — security issues S1-S5 + bug tracker
- [DO_NEXT.md](DO_NEXT.md) — immediate next actions
- [STATUS.md](STATUS.md) — current metrics
- [UPSTREAM_STATUS.md](UPSTREAM_STATUS.md) — full upstream catalogue
- [docs/SECURITY_AUDIT.md](docs/SECURITY_AUDIT.md) — CVEs and vulnerability details
158 changes: 115 additions & 43 deletions PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,65 +2,137 @@

> **Frankencode** is a fork of [OpenCode](https://github.com/anomalyco/opencode) (`dev` branch) that adds context editing, content-addressable storage, and an edit graph.

**Status (2026-03-21):** Features implemented. 51 bugs fixed, 0 open. Type safety audit complete (20 documented `any` remain). 1448 tests passing, 0 tsgo errors. See `STATUS.md`.
**Status (2026-03-21):** All features implemented. 51 bugs fixed, 5 security issues open. Type safety complete. Zod v4 migrated. 1473 tests passing, 0 tsgo errors.

**Upstream divergence:** 23 ahead, 162 behind, ~195 open PRs catalogued. See [UPSTREAM_STATUS.md](UPSTREAM_STATUS.md).

---

## Phase 1: Security Fixes (CRITICAL)

Fix the 5 security issues documented in [BUGS.md](BUGS.md) and [docs/SECURITY_AUDIT.md](docs/SECURITY_AUDIT.md).

| # | Issue | Severity | Fix |
|---|-------|----------|-----|
| S1 | `Filesystem.contains()` symlink bypass | CRITICAL | Add `realpathSync()` before lexical check in `util/filesystem.ts` |
| S2 | `exec()` command injection in github.ts | HIGH | Replace `exec(cmd)` with `spawn(["open", url])` |
| S3 | Untrusted `.opencode/` autoloading | HIGH | Add workspace trust prompt before loading MCP/plugins |
| S4 | Server unauthenticated on non-loopback | MED | Require password or bind loopback-only by default |
| S5 | Read tool exposes .env files | MED | Add sensitive file deny-list |

Also evaluate upstream security PRs:
- [#10763](https://github.com/anomalyco/opencode/pull/10763) — CVE-2025-58179 fix
- [#10974](https://github.com/anomalyco/opencode/pull/10974) — TUI server exposure guard
- [#14581](https://github.com/anomalyco/opencode/pull/14581) — Cross-drive path bypass (Windows)

**Exit criteria:** All S1-S5 fixed, regression tests added, `BUGS.md` updated.

---

## Phase 2: High-Priority Upstream Bug Fixes

Cherry-pick 8 high-priority fixes from vouched contributors and critical bug reports. See [UPSTREAM_STATUS.md](UPSTREAM_STATUS.md) Phase 1.

| SHA/PR | Author | Fix | Size |
|--------|--------|-----|------|
| `cc818f803` / #18283 | Protocol Zero | thinkingConfig only for reasoning models | Small |
| `7866dbcfc` / #18292 | Luke Parker | truncate permission import cycle | Small |
| `d69962b0f` / #18264 | James Long | disable chunk timeout by default | Small |
| `054075189` / #18259 | James Long | queue for event route processing | Small |
| `0d7e62a53` / #17815 | Kit Langton | forked prompt attachments losing file parts | Small |
| `84e62fc66` / #18165 | Kit Langton | preserve tagged error messages | Small |
| [#18527](https://github.com/anomalyco/opencode/pull/18527) | Dax Raad (Vouched) | restore SIGHUP exit handler | 1 line |
| [#18113](https://github.com/anomalyco/opencode/pull/18113) | Ariane Emory (Vouched) | fix default timeout value | 2 lines |

**Exit criteria:** All 8 cherry-picked, tests pass, no regressions.

---

## Next: Zod v3 → v4 Migration
## Phase 3: Upstream Quality Fixes + OpenTUI Upgrade

| SHA/PR | Author | Fix |
|--------|--------|-----|
| `040f551c5` / #18079 | Sebastian | OpenTUI 0.1.88 upgrade |
| [#18551](https://github.com/anomalyco/opencode/pull/18551) | Sebastian (Vouched) | OpenTUI 0.1.90 upgrade |
| `2dbcd79fd` / #18261 | jorge g | stabilize agent/skill ordering |
| `4b4dd2b88` / #18009 | Ariane Emory | apply_patch in EDIT_TOOLS filter |
| `5ddfe4ada` / #18123 | Kit Langton | type Provider.list() properly |
| `fee3c196c` / #17812 | Kit Langton | prompt schema validation debug logs |

See details below.
Also evaluate community bug fix PRs (~17 candidates, see UPSTREAM_STATUS.md):
- Retry backoff cap, 429 retry, lone surrogate prevention, empty content filtering
- LSP memory leak fix, MCP client recovery, snapshot git timeout

**Exit criteria:** OpenTUI upgraded, quality fixes applied, tests pass.

---

## Future: Zod v3 → v4 Migration
## Phase 4: Community Bug Fixes + Features

Cherry-pick or reimplement the best community contributions:

The codebase uses Zod v4 (`zod` package) but some patterns and downstream libraries (`zod-to-json-schema`, `hono-openapi`) expect Zod v3 types. Sites needing conversion:
**Bug fixes:**
- [#18539](https://github.com/anomalyco/opencode/pull/18539) — discourage _noop tool call during compaction
- [#18538](https://github.com/anomalyco/opencode/pull/18538) — handle SSE client disconnect
- [#18443](https://github.com/anomalyco/opencode/pull/18443) — retry 429 even when non-retryable
- [#17758](https://github.com/anomalyco/opencode/pull/17758) — prevent lone surrogate 400 errors
- [#17742](https://github.com/anomalyco/opencode/pull/17742) — filter empty text content blocks
- [#18137](https://github.com/anomalyco/opencode/pull/18137) — reduce memory during prompting (BYK)
- [#18516](https://github.com/anomalyco/opencode/pull/18516) — prevent subagent plan escape (BYK)
- [#17635](https://github.com/anomalyco/opencode/pull/17635) — remove dead LSP clients (memory leak)

| File | Pattern | Issue |
|------|---------|-------|
| `server/routes/experimental.ts:91` | `zodToJsonSchema(t.parameters as any)` | `zod-to-json-schema` expects Zod v3 `ZodType`, not v4 |
| `server/routes/*.ts` | `resolver()`, `validator()` from `hono-openapi` | May expect v3 schemas |
| `util/json.ts` | `JsonValue` uses `z.any()` with cast | `z.lazy()` generates `__schema0` $ref breaking SDK generation |
| `session/message-v2.ts` | `z.toJSONSchema()` | Uses Zod v4 native JSON Schema generation |
| `util/effect-zod.ts` | Effect-to-Zod bridge | Converts between Effect Schema and Zod |
**Features (evaluate):**
- [#12633](https://github.com/anomalyco/opencode/pull/12633) — auto-accept mode for TUI permissions (Dax)
- [#18317](https://github.com/anomalyco/opencode/pull/18317) — quiet mode for CLI runs
- [#18235](https://github.com/anomalyco/opencode/pull/18235) — offline mode
- [#18450](https://github.com/anomalyco/opencode/pull/18450) — native Output.object() (net code deletion)

**Action:** Audit all `zod-to-json-schema` call sites. Either migrate to Zod v4's `z.toJSONSchema()` or keep the v3 compatibility cast. Separate PR.
**Exit criteria:** Selected fixes applied, features evaluated, tests pass.

---

## Future: Upstream Re-sync
## Phase 5: Remaining Tests

Upstream (`anomalyco/opencode`) continues to diverge. The Effect-ification migration is ongoing upstream (7+ PRs still open). Key areas of conflict:
- [ ] filterEdited unit tests (hidden parts stripped, empty messages dropped)
- [ ] ContextEdit validation tests (ownership, budget, recency, privileged agents)
- [ ] TUI dialog tests (9: command, provider, session-rename, stash, etc.)
- [ ] TUI interaction tests (keyboard nav, prompt input, command palette)

**Exit criteria:** Test count increases, coverage gaps filled.

---

## Phase 6: Effect Behavioral Analysis

For each of the 12 upstream Effect PRs, extract behavioral changes and reimplement in our architecture. NOT a rebase.

Key PRs to analyze:
- #17544 — LayerMap (foundational, already done differently)
- #17849 — SkillService (we have content cache — check for new capabilities)
- #18483 — InstanceState consolidation (extract any bug fixes)
- #17829 — VcsService (contains HEAD filter bug fix)
- #17835 — FileTimeService (Semaphore locks — evaluate benefit)

**Exit criteria:** Behavioral changes extracted and reimplemented where valuable.

---

| Area | Risk | Notes |
|------|------|-------|
| `session/prompt.ts` | High | Our filterEdited/filterEphemeral/focus injection vs upstream pipeline changes |
| `session/message-v2.ts` | High | Our EditMeta/LifecycleMeta/JsonValue vs upstream schema changes |
| `effect/` | Medium | Upstream consolidating into InstanceState; we deleted Instance entirely |
| `skill/skill.ts` | High | Upstream rewrote to Effect service; we added content cache |
| New Frankencode files | None | CAS, edit graph, context tools, side threads — no upstream conflict |
## Backlog: Features

**Strategy:** Periodic rebase onto `upstream/dev`. Cherry-pick applicable fixes first, then full rebase.
- [ ] TUI rendering of edit indicators (hidden/replaced/annotated parts)
- [ ] CAS garbage collection improvements (size limits, age-based cleanup)
- [ ] TUI features from upstream PRs (sidebar position, /edit command, syntax highlighting)

---

## Completed Features

| Feature | Status | PR |
|---------|--------|-----|
| Plan Mode Fixes | Done | — |
| Verification Tool | Done | — |
| Progressive Disclosure | Done | — |
| Skills as Scripts | Done | — |
| Evaluator-Optimizer | Done | — |
| Bug Fix Pass (46 bugs) | Done | #10, #12 |
| Upstream Bug Backport P1 (B1-B9) | Done | #16 |
| Upstream Bug Backport P2 (B10-B16) | Done | #17 |
| Upstream Backport P3 (B17-B22) | Done | #18 |
| Upstream Full Rebase (Phase 4) | Done | #19 |
| Effect-ification B1 (state maps) | Done | #20 |
| Effect-ification B2-B10g + Instance deletion | Done | #21 |
| Bug fixes B47-B52 | Done | #22 |
| Type safety audit (~236 `any` eliminated) | Done | #22 |
| Architecture docs (Effect, ACP, Providers) | Done | #22 |
| Strong Zod schemas (JsonValue, ProviderMeta, ToolInput, ToolMeta) | Done | #22 |
## Completed (PRs #16-#25)

| Feature | PR |
|---------|-----|
| Upstream bug backports (B1-B22) | #16-#18 |
| Upstream full rebase | #19 |
| Effect-ification (Instance deleted, 0 ALS fallbacks, 81 TUI tests) | #20-#21 |
| Bug fixes B47-B52 + type safety (~250 `any` eliminated) + architecture docs | #22 |
| TUI types + logger types | #23 |
| Zod v4 migration + 25 Frankencode unit tests | #24 |
| Upstream catalogue + security audit | #25 |
Loading
Loading