-
Notifications
You must be signed in to change notification settings - Fork 10
feat(octto): add browser-based brainstorming system #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The context-injector hook was using snake_case 'file_path' but OpenCode tools use camelCase 'filePath', causing directory context injection to silently fail for all file read/edit operations. - Change input.args?.file_path to input.args?.filePath - Add tests for context injection behavior
Wrap spawn() call in try-catch to provide descriptive error messages when command not found or other spawn failures occur. - Add try-catch around bun-pty spawn() call - Throw descriptive error with command name and original message - Add test for command not found scenario - Note: bun-pty silently ignores invalid workdir (library limitation)
Add src/utils/config.ts with compile-time constants organized by domain: - compaction: threshold, cooldown, timeout settings - contextWindow: warning/critical thresholds - tokens: estimation settings - paths: ledger dirs, context files, patterns - timeouts: btca, toast durations - limits: file sizes, PTY buffer, cache settings Add comprehensive tests in tests/utils/config.test.ts (29 tests)
When a user configures an agent with an unavailable provider/model in micode.json, instead of crashing at runtime, we now: - Validate models at plugin startup against available providers - Log a warning for invalid models - Remove the invalid model from config, letting the agent use its default Handles edge cases: empty strings, malformed models (no slash), and models with multiple slashes in the ID. Closes #10
Update hooks and tools to use the new utility modules: - auto-compact: config.* for thresholds/timeouts, extractErrorMessage - context-injector: config.paths.* and config.limits.* - context-window-monitor: config.contextWindow.* - ledger-loader: config.paths.ledgerDir/ledgerPrefix - token-aware-truncation: config.tokens.* - artifact-auto-index: log.error instead of console.error Part of tech debt remediation (Phase 3).
Integrate octto (interactive browser-based brainstorming) into micode as a separate primary agent alongside the existing brainstormer. Infrastructure (src/octto/): - session/: HTTP server + WebSocket for browser communication - state/: Brainstorm state persistence to thoughts/brainstorms/ - ui/: Self-contained HTML/CSS/JS bundle for browser UI - types.ts: 15+ question type configurations Tools (src/tools/octto/): - brainstorm.ts: create_brainstorm, await_brainstorm_complete, end_brainstorm - questions.ts: 15 question type tools (pick_one, confirm, slider, etc.) - responses.ts: get_answer, get_next_answer, list_questions - session.ts: start_session, end_session - processor.ts: Answer processing with probe agent integration Agents (src/agents/): - octto.ts: Primary orchestrator for brainstorm sessions - bootstrapper.ts: Creates 2-4 exploration branches from request - probe.ts: Evaluates branch Q&A and generates follow-up questions Config: - Added octto section to src/utils/config.ts with timeouts and limits - ID generators moved to octto/session/utils.ts (single source of truth)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
20 issues found across 53 files
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="src/octto/ui/bundle.ts">
<violation number="1" location="src/octto/ui/bundle.ts:733">
P1: Hard-coding `ws://` makes the UI fail to connect when served over HTTPS because browsers block mixed-content WebSocket calls. Derive the protocol from `window.location.protocol` and use `wss://` when the page is loaded via HTTPS.</violation>
<violation number="2" location="src/octto/ui/bundle.ts:1263">
P2: Rate answers are recorded incorrectly: `setRating` marks every star up to the chosen value as `.selected`, but `submitRate` only reads the first `.selected` button, so higher ratings are never captured. Store the chosen value explicitly (e.g., via a data attribute) or select the highest `.selected` element before submitting.</violation>
</file>
<file name="src/octto/state/store.ts">
<violation number="1" location="src/octto/state/store.ts:155">
P1: `deleteSession` bypasses the per-session lock, so concurrent writes can recreate a session immediately after it is deleted.</violation>
</file>
<file name="src/octto/session/sessions.ts">
<violation number="1" location="src/octto/session/sessions.ts:208">
P1: `getAnswer` marks the entire question as TIMEOUT when a single wait call times out, so later user responses are silently dropped because `handleWsMessage` only processes PENDING questions.</violation>
</file>
<file name="src/config-loader.ts">
<violation number="1" location="src/config-loader.ts:122">
P2: `override.model` is assumed to be a string, but malformed configs can make it a non-string, causing `.trim()` to throw during validation.</violation>
</file>
<file name="src/octto/types.ts">
<violation number="1" location="src/octto/types.ts:184">
P2: `ShowPlanConfig.sections` is required even though `markdown` is documented as an alternative; make `sections` optional so callers can supply only `markdown`.</violation>
</file>
<file name="src/octto/constants.ts">
<violation number="1" location="src/octto/constants.ts:11">
P2: `DEFAULT_MAX_QUESTIONS` is hard-coded to 15 instead of being re-exported from `config.octto`, contradicting the stated single source of truth and risking divergence when the config changes.</violation>
</file>
<file name="src/octto/session/waiter.ts">
<violation number="1" location="src/octto/session/waiter.ts:60">
P2: Ensure the waiter is removed even when the callback throws; otherwise a failing waiter stays registered and blocks future notifications for that key.</violation>
<violation number="2" location="src/octto/session/waiter.ts:77">
P2: Wrap the notification loop in a `try/finally` so the waiter list is always cleared even when a callback throws; otherwise the key remains registered forever after an exception.</violation>
</file>
<file name="src/tools/octto/session.ts">
<violation number="1" location="src/tools/octto/session.ts:18">
P2: The `start_session` schema blocks valid octto question types (rank, rate, ask_image, etc.), so sessions containing those questions cannot be started even though the system supports them.</violation>
</file>
<file name="src/tools/milestone-artifact-search.ts">
<violation number="1" location="src/tools/milestone-artifact-search.ts:20">
P1: `searchMilestoneArtifacts` is never implemented on `ArtifactIndex`, so this tool throws before returning any results.</violation>
</file>
<file name="src/agents/octto.ts">
<violation number="1" location="src/agents/octto.ts:43">
P2: Design documents are instructed to be written to `thoughts/shared/plans/...` even though brainstorming outputs must live under `thoughts/shared/designs/`, so this prompt would misfile every design artifact.</violation>
</file>
<file name="src/octto/session/server.ts">
<violation number="1" location="src/octto/session/server.ts:19">
P2: Bind the brainstorming server to the loopback interface (e.g., hostname 127.0.0.1) so brainstorming sessions are not exposed on all network interfaces.</violation>
</file>
<file name="thoughts/shared/designs/2026-01-16-milestone-artifact-indexing-design.md">
<violation number="1" location="thoughts/shared/designs/2026-01-16-milestone-artifact-indexing-design.md:34">
P3: The metadata section is duplicated (“Metadata Fields” and “Metadata Fields (Explicit)”) with identical content, which makes the design doc harder to read and suggests there might be a missing distinction.</violation>
</file>
<file name="src/index.ts">
<violation number="1" location="src/index.ts:117">
P2: `octtoSessionsMap` is never populated, so the new session-deletion cleanup never ends octto sessions, leading to leaked browser/WebSocket sessions for each user session.</violation>
</file>
<file name="src/tools/octto/formatters.ts">
<violation number="1" location="src/tools/octto/formatters.ts:9">
P2: `escapeXml` does not escape quotes, so attribute values containing `"` or `'` will break the generated XML and allow injection. Extend the helper to encode quotes before reusing it for attributes.</violation>
</file>
<file name="src/tools/octto/questions.ts">
<violation number="1" location="src/tools/octto/questions.ts:122">
P2: rate tool omits the `labels` configuration defined in `RateConfig`, preventing callers from supplying the min/max labels the UI supports.</violation>
<violation number="2" location="src/tools/octto/questions.ts:193">
P2: ask_image ignores the `accept` whitelist from `AskImageConfig`, so callers cannot restrict allowed image types and the frontend can’t enforce MIME/extension safety.</violation>
<violation number="3" location="src/tools/octto/questions.ts:451">
P2: slider tool never accepts the `labels` object defined in `SliderConfig`, so callers can’t provide min/mid/max labels and the UI cannot display them.</violation>
</file>
<file name="tests/utils/logger.test.ts">
<violation number="1" location="tests/utils/logger.test.ts:72">
P2: `require` is not available in this ESM test file, so deleting `require.cache[...]` will throw and break the debug test. Use an ESM-friendly cache-busting approach instead (e.g., dynamic import with a query string).</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| execute: async (args) => { | ||
| try { | ||
| const index = await getArtifactIndex(); | ||
| const results = await index.searchMilestoneArtifacts(args.query, { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P1: searchMilestoneArtifacts is never implemented on ArtifactIndex, so this tool throws before returning any results.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/tools/milestone-artifact-search.ts, line 20:
<comment>`searchMilestoneArtifacts` is never implemented on `ArtifactIndex`, so this tool throws before returning any results.</comment>
<file context>
@@ -0,0 +1,48 @@
+ execute: async (args) => {
+ try {
+ const index = await getArtifactIndex();
+ const results = await index.searchMilestoneArtifacts(args.query, {
+ milestoneId: args.milestone_id,
+ artifactType: args.artifact_type,
</file context>
| const ratings = {}; | ||
| for (const opt of (q.config.options || [])) { | ||
| const container = document.getElementById('rate_' + questionId + '_' + opt.id); | ||
| const selected = container.querySelector('.rate-star.selected'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: Rate answers are recorded incorrectly: setRating marks every star up to the chosen value as .selected, but submitRate only reads the first .selected button, so higher ratings are never captured. Store the chosen value explicitly (e.g., via a data attribute) or select the highest .selected element before submitting.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/octto/ui/bundle.ts, line 1263:
<comment>Rate answers are recorded incorrectly: `setRating` marks every star up to the chosen value as `.selected`, but `submitRate` only reads the first `.selected` button, so higher ratings are never captured. Store the chosen value explicitly (e.g., via a data attribute) or select the highest `.selected` element before submitting.</comment>
<file context>
@@ -0,0 +1,1599 @@
+ const ratings = {};
+ for (const opt of (q.config.options || [])) {
+ const container = document.getElementById('rate_' + questionId + '_' + opt.id);
+ const selected = container.querySelector('.rate-star.selected');
+ if (selected) {
+ ratings[opt.id] = parseInt(selected.dataset.value);
</file context>
| - created_at | ||
| - tags | ||
|
|
||
| # Metadata Fields (Explicit) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P3: The metadata section is duplicated (“Metadata Fields” and “Metadata Fields (Explicit)”) with identical content, which makes the design doc harder to read and suggests there might be a missing distinction.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At thoughts/shared/designs/2026-01-16-milestone-artifact-indexing-design.md, line 34:
<comment>The metadata section is duplicated (“Metadata Fields” and “Metadata Fields (Explicit)”) with identical content, which makes the design doc harder to read and suggests there might be a missing distinction.</comment>
<file context>
@@ -0,0 +1,65 @@
+- created_at
+- tags
+
+# Metadata Fields (Explicit)
+- milestone_id (stored in metadata for filtering and retrieval)
+- artifact_type
</file context>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1 issue found across 15 files (changes from recent commits).
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="tests/indexing/search/milestone-search.test.ts">
<violation number="1" location="tests/indexing/search/milestone-search.test.ts:56">
P2: `index.close()` is only called on the happy path; if any assertion throws, the SQLite handle stays open and can make tests flaky. Wrap the test body in try/finally (or move the close to afterEach) so cleanup always runs.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
- Read available models from opencode.json synchronously during init - Validate user model overrides in micode.json against available models - Invalid models fall back to opencode default with warning - Remove hardcoded model from agents (use opencode default) - Update @opencode-ai/plugin to 1.1.23 - Fix plugin entry point to use dist/index.js
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2 issues found across 19 files (changes from recent commits).
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="src/config-loader.ts">
<violation number="1" location="src/config-loader.ts:123">
P2: Model overrides are always rejected when opencode.json cannot be loaded. If loadAvailableModels returns an empty set (missing/invalid config), the code treats every model as invalid and strips the override. Consider skipping validation when no models are available so user overrides still work in that case.</violation>
</file>
<file name="package.json">
<violation number="1" location="package.json:5">
P1: `module`/`main` now point to `dist/index.js`, but the package publish allowlist excludes `dist/`, so the entrypoint will be missing from the published package.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
Root cause: prompt had conflicting instructions - meta-rules said "be proactive" but specific phase instructions said "ask ONE question" and "wait for feedback". Models follow specific instructions over meta-rules. Changes: - Add <identity> section framing agent as senior engineer - Rewrite exploring phase: "wait for feedback" -> "MAKE THE DECISION" - Remove all "ask question" patterns throughout - Update presenting phase to proceed without asking for approval - Fix description: "collaborative questioning" -> "decisive collaboration"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1 issue found across 3 files (changes from recent commits).
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="src/config-loader.ts">
<violation number="1" location="src/config-loader.ts:112">
P2: Model override validation is effectively disabled when mergeAgentConfigs is called without availableModels (the common path), so invalid model IDs will be accepted and applied. This contradicts the documented behavior and can lead to invalid model configuration at runtime.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
Summary
Integrates octto (interactive browser-based brainstorming) into micode as a separate primary agent alongside the existing brainstormer.
thoughts/brainstorms/Changes
Infrastructure (
src/octto/)session/: HTTP server + WebSocket for browser communicationstate/: Brainstorm state persistenceui/: Self-contained HTML/CSS/JS bundle for browser UItypes.ts: 15+ question type configurationsTools (
src/tools/octto/)brainstorm.ts: create_brainstorm, await_brainstorm_complete, end_brainstormquestions.ts: 15 question type toolsresponses.ts: get_answer, get_next_answer, list_questionssession.ts: start_session, end_sessionprocessor.ts: Answer processing with probe agent integrationAgents (
src/agents/)octto.ts: Primary orchestrator for brainstorm sessionsbootstrapper.ts: Creates 2-4 exploration branches from requestprobe.ts: Evaluates branch Q&A and generates follow-up questionsConfig
octtosection tosrc/utils/config.tswith timeouts and limitsoctto/session/utils.ts(single source of truth)Test plan
bun run buildpassesbun testpasses (200 tests, 1 pre-existing failure unrelated to octto)Summary by cubic
Add octto: a browser-based brainstorming agent with branch-based exploration, interactive Q&A, and state saved to thoughts/brainstorms/. Also adds milestone artifact indexing and search plus safer startup through model validation and error handling.
New Features
Bug Fixes
Written for commit ec46a3a. Summary will update on new commits.