5 Commits

Author SHA1 Message Date
Michael Ramos 3de555f5e5 Fix OpenCode plugin runtime compatibility (#849)
* fix(opencode): add host-compatible runtime bridge

* fix(opencode): preserve parity in cli bridge

* test(opencode): add isolated sandbox launcher

* test(opencode): keep reusable sandbox launchers

* test(opencode): export local plugin default

* test(opencode): install OpenChamber deps when needed

* test(opencode): avoid OpenChamber default port collision

* fix(opencode): harden cli bridge fallback

* test(opencode): clean isolated sandbox helpers
2026-06-04 18:14:05 -07:00
Hrand Liu e0aee7451b feat: add PLANNOTATOR_DATA_DIR env var to customize data directory (#795)
* feat: add PLANNOTATOR_DATA_DIR env var to customize data directory

* fix: update missed hardcoded paths to use PLANNOTATOR_DATA_DIR

OpenCode plugin and VS Code extension still used hardcoded
~/.plannotator paths, causing the IPC registry and plan backing
file to diverge from the server when PLANNOTATOR_DATA_DIR is set.

Also exports data-dir from @plannotator/shared and documents the
new env var in AGENTS.md.

Co-authored-by: Chris Werner Rau <14326070+cwrau@users.noreply.github.com>
Co-authored-by: João O. Santos <34689526+Joao-O-Santos@users.noreply.github.com>

* fix: vendor data-dir.ts into Pi extension and rewrite imports

The Pi extension copies shared/server modules into generated/ at
build time. Without vendoring data-dir.ts and rewriting the
parent-relative imports, typecheck fails on all generated files
that import getPlannotatorDataDir.

* refactor: eliminate duplicated data-dir logic and clean up call sites

- VS Code extension: replace inlined getPlannotatorDataDir() copy with
  import from the canonical packages/shared/data-dir.ts (esbuild bundles
  it, so no runtime dependency needed)
- storage.ts: hoist repeated getPlannotatorDataDir() calls to a
  module-level DATA_DIR constant, matching the pattern config.ts uses
- data-dir.ts: remove inaccurate docstring claim about relative path
  resolution (the code does not call resolve())
- improvement-hooks.ts: hoist to DATA_DIR constant, clarify comments
  on the two-level hook lookup (hooks/ subdir vs root fallback)

* fix: resolve relative PLANNOTATOR_DATA_DIR to absolute path

A relative value like ./data would break readArchivedPlan's path
traversal guard, which compares a resolve()'d absolute path against
the still-relative planDir prefix. Always return an absolute path
so all callers get consistent path shapes.

* fix: use @plannotator/shared/data-dir imports in server package

Switch from relative ../shared/data-dir imports to the package
export, matching the convention every other server file follows.
Update Pi vendor script sed rules to match the new import style.

* fix: use package imports in server and respect data dir in compound skill

Server modules: switch from relative ../shared/data-dir imports to
@plannotator/shared/data-dir, matching the convention every other
server file follows. Update Pi vendor script sed rules to match.

Compound skill: update hardcoded ~/.plannotator paths to check
PLANNOTATOR_DATA_DIR first, so the skill reads plans and writes
the improvement hook to the correct location when users set a
custom data directory.

Co-authored-by: Chris Werner Rau <14326070+cwrau@users.noreply.github.com>
Co-authored-by: João O. Santos <34689526+Joao-O-Santos@users.noreply.github.com>

* fix: remove remaining hardcoded ~/.plannotator assumptions

- Settings UI: replace hardcoded path in label and placeholder with
  generic text that doesn't assume a specific data directory
- quickLabels: update agent tip to reference PLANNOTATOR_DATA_DIR
  so the agent checks the correct plans directory
- codex-review: hoist getPlannotatorDataDir() to module-level DATA_DIR
  constant, eliminating redundant per-call resolution in debugLog()
- Tests: make submit-plan and storage tests resilient to
  PLANNOTATOR_DATA_DIR being set in the environment
- Install scripts (sh, ps1, cmd): check PLANNOTATOR_DATA_DIR before
  falling back to ~/.plannotator for config.json attestation lookup

* fix: expand tilde in install script and update test assertions

install.sh: PLANNOTATOR_DATA_DIR set to ~/... stays literal inside
double quotes, so the config file check silently failed. Add case
statement to expand ~ the same way the runtime data-dir.ts does.

install.test.ts: update three assertions that checked for hardcoded
~/.plannotator paths — now verify PLANNOTATOR_DATA_DIR awareness
instead.

* docs: add PLANNOTATOR_DATA_DIR to env var reference with VS Code note

Document the new env var on the marketing site's environment
variables reference page. Include a footnote about ensuring
VS Code inherits the variable when launched from the Dock.

---------

Co-authored-by: Michael Ramos <mdramos8@gmail.com>
Co-authored-by: Chris Werner Rau <14326070+cwrau@users.noreply.github.com>
Co-authored-by: João O. Santos <34689526+Joao-O-Santos@users.noreply.github.com>
2026-05-26 14:56:07 -07:00
Robert Dailey 29390c9e71 fix(opencode): store active plan backing file outside workspace (#743)
The backing file used for edit-based plan submission was stored at
.opencode/plans/_active-plan.md inside the workspace, causing it to
appear in git status and editor file trees. It is now stored at
~/.plannotator/active/{project}/_active-plan.md alongside the version
history.

- Move getPlanBackingPath to derive path from project name under
  ~/.plannotator/active/
- Derive project name from ctx.directory basename via sanitizeTag at
  call site
- Delete backing file on approval since it is no longer needed after the
  session ends
- Update tests to reflect new path contract
2026-05-18 17:17:48 -07:00
Robert Dailey b3f1deb8d3 fix(opencode): skip end bounds check on empty file in validateEdits (#752)
When a file has no content (lineCount === 0), any edit is a pure insert
and the end field is semantically irrelevant. The previous check
rejected payloads where end was present on an empty file because end >
lineCount always evaluated true, breaking first-call submit_plan
invocations from agents or frameworks that include end unconditionally.

- Skip end > lineCount validation when lineCount === 0; applyEdits
  handles it via splice clamping
- Add applyEdits test: edit on empty file with start=1, end=1 produces
  correct output
- Add validateEdits test: passes for empty file with start=1 and end=1

Fixes #742
2026-05-18 17:17:09 -07:00
Robert Dailey 807cc5f09b feat(submit-plan): replace dual-mode with edit-based interface (#730)
* feat(submit-plan): replace text/file-path mode with edit-based interface

Switches the OpenCode submit_plan tool from a dual-mode interface
(inline text or file path) to an edit-based one. The plugin now owns a
backing file at .opencode/plans/_active-plan.md; the agent never reads
or writes it directly. On denial, the response includes the current plan
with line numbers so the agent can apply surgical edits instead of
resubmitting the entire document, reducing token waste on iterative
revisions.

- Add applyEdits, validateEdits, formatWithLineNumbers, and
  getPlanBackingPath helpers to the plugin
- Validate edit ranges (bounds, overlap, size limit) before mutating the
  backing file
- Return line-numbered plan in denial responses to anchor targeted edits
- Remove getPlanDirectory, validatePlanPath, and file-path auto-
  detection from plan-mode.ts
- Replace plan-mode.test.ts path-validation coverage with submit-
  plan.test.ts for the edit engine
- Update custom-feedback.md and opencode.md docs for edit-based
  semantics

Refs #365

* chore(opencode): drop unused buildPlanFileRule import

Removed in PR #730 deny path along with the only call site, but the
import was left behind.

---------

Co-authored-by: Michael Ramos <mdramos8@gmail.com>
2026-05-15 09:54:04 -07:00