You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: audit findings + subagent prompt visibility + discord link
Three logical groups of fixes bundled together.
## A. Hide subagent prompts from TUI render (issue #50 part 2)
Historian, dreamer, sidekick, compressor, and user-memory subagent calls
were sending their full system prompt body as a regular `text` part on
the user message. OpenCode TUI rendered this as a giant unreadable
"user message" in the subagent pane (compaction prompts can be >90K
chars).
Fix: add `synthetic: true` to the prompt text part on all 7 subagent
call sites. Verified via OpenCode source:
- `message-v2.ts:74` (toModelMessagesEffect) only filters `!part.ignored`
for user-role text, so synthetic still reaches the LLM.
- `transcript.ts:85` filters `!part.synthetic` for TUI render, hiding
the prompt body from the visible pane.
- OpenCode's own `compaction.ts:547` and `prompt.ts:234-241` use the
same pattern — the LLM must read these prompts to function.
E2E proof: `historian-success.test.ts` still passes (29/29 e2e tests
pass) — if synthetic filtered the prompt out, historian would receive
empty input and produce no compartment; the test asserts a compartment
is published.
## B. Audit findings — 8 confirmed real bugs + 2 false-positive comments
Council audit of the post-v0.16.1 stack identified 10 issues. Manual
re-verification against source confirmed 8 real bugs and 2 false
positives.
### Real bugs
1. `setup-opencode.ts` cast `existing.plugin as string[]` and called
`.startsWith()` on each entry, throwing TypeError on tuple-form
`["@pkg/name", { ...options }]` entries. Now imports
`isDevPathPluginEntry` and `matchesPluginEntry` from the shared
adapter and operates on the raw array. Tuples preserved on write,
dev-path entries detected (no double-add) but never replaced.
2. `doctor-opencode.ts` filtered the plugin array with
`(p): p is string => typeof p === "string"` BEFORE writing it
back, silently destroying every tuple entry on every doctor run.
Same fix: operate on the raw array. When upgrading a pinned tuple
entry to @latest, the options object is preserved by mutating only
index [0] of the tuple. Same fix applied to TUI config plugin
handling. Also fixes finding #9: the inline `isDevPathEntry` only
matched `opencode-magic-context`, missing bare `magic-context` paths
(post-rename) that the shared helper handles correctly.
3. `paths.ts::getOpenCodePluginCacheDir` had a Windows branch
resolving to `%LOCALAPPDATA%/opencode/Cache/packages` while
OpenCode (and our `data-path.ts` plugin helper) actually use
`~/.cache/opencode/packages` on every platform via the
`xdg-basedir` fallback. Removed the Windows-specific branch so
`doctor --force` clears the right directory. This regressed the
exact same fix already applied to `data-path.ts`.
4. `dashboard-release.yml` deploy-updater used `publish_dir: .` +
`force_orphan: true` + `keep_files: false` together with an
invalid `include_files` input that peaceiris/actions-gh-pages does
not support. Result: every dashboard release published the entire
repo checkout to gh-pages with a single orphan commit, wiping
history. Fixed by staging just `latest.json` in `_updater_publish/`,
pointing `publish_dir` at that dir, setting `keep_files: true` and
`force_orphan: false`.
5. `dashboard-release.yml` used a hardcoded `sleep 30` before
downloading `latest.json` from the draft release. First-time
asset uploads can take longer than 30s, causing silent failures.
Replaced with a 20×15s retry loop (5 minutes total).
8. `release.yml` `github-release` job depended only on test jobs, not
on the three publish jobs, so a release page could be created on
GitHub while one of the @cortexkit/* npm packages was missing.
Now `needs: [..., publish-npm, publish-npm-pi, publish-npm-cli]`.
10. `doctor-pi.ts` had `add(results, "pass", "No known conflicting Pi
extensions detected")` hardcoded with no detection logic. Replaced
with real check for multiple magic-context entries in Pi
`packages[]` (a real self-conflict that loads the plugin twice).
### False positives — documented inline
6. `setup-opencode.ts` Step 8 (OMO conflict prompt) is gated by
`!hadExistingSetup`. Audit flagged this as "skipped for existing
users", but existing users hit the same OMO conflict-fix logic via
the `hadExistingSetup` branch at lines 231-257 (which calls
`detectConflicts` + `fixConflicts` covering all OMO hooks). Added
inline comment so future audits don't re-flag.
7. `migrate.ts` reports `messageCount: entries.length - 2`. Audit
flagged this as off-by-N. The `- 2` correctly subtracts the
structural `session` + `model_change` entries that lead every Pi
JSONL file; the result counts boundary marker + all migrated
message entries + (when present) compaction marker — exactly what
"migrated entries" means in CLI output. Added inline comment.
## C. Discord URL update
Switched README Discord badge + nav link from `discord.gg/F2uWxjGnU`
to `discord.gg/DSa65w8wuf`.
## Verification
- typecheck: 0 errors across plugin + pi-plugin + cli
- lint: 0 errors (after biome autofix)
- plugin tests: 1050 / 1050 pass
- pi-plugin tests: 236 / 236 pass
- cli tests: 58 / 58 pass
- e2e tests: 29 / 29 pass (proves synthetic:true reaches LLM)
- manual smoke tests:
- tuple-form other plugin preserved when adding magic-context: ✓
- pinned tuple of magic-context upgraded to @latest, options
preserved (`myOption` survives `0.16.0 → @latest`): ✓
- dev-path entry detected (hasDev=true), not double-added: ✓
- bare `magic-context` (post-rename) dev path detected: ✓
## Reusable helpers
`isDevPathPluginEntry` and `matchesPluginEntry` were promoted from
private to exported in `packages/cli/src/adapters/opencode.ts` so
both `setup-opencode.ts` and `doctor-opencode.ts` can use the same
source of truth for plugin-entry classification — eliminates the
drift that caused finding #9.
0 commit comments