feat(extension): bug-session orchestration + lifecycle (harmoniqs/amicode#249) - #251

Merged
jeonghun-jj-lee merged 24 commits into
mainfrom
amico/issue-249-bug-report
Aug 7, 2026
Merged

feat(extension): bug-session orchestration + lifecycle (harmoniqs/amicode#249)#251
jeonghun-jj-lee merged 24 commits into
mainfrom
amico/issue-249-bug-report

Conversation

@jeonghun-jj-lee

@jeonghun-jj-leejeonghun-jj-lee commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Part of #249 — the extension slice of the machine-managed bug-session feature. Lifecycle spec: docs/adr/0004-bug-session-lifecycle.md (on main).

Carries:

  • Orchestrate bug sessions from the extension: amicode.reportBug command, context envelope, lifecycle handler #250amicode.reportBug command, context envelope (bug_report session metadata), bridge allowlist additions, machine-managed lifecycle (filed → archive + close-bug-report; abandoned → abort + hard delete; failure → no orphans), single-open invariant, boot param re-pinned from the staged skill set.
  • QA fix (preview dogfood) — the bug-report-poke up-kind: relay Lane-1 admission, bridge route, and BugReportManager.poke() — re-posts open-bug-report when a bug session is live (joins an in-flight create, never double-creates), silence otherwise. Plus [bug] lifecycle log lines for the open/poke paths. 5 new vitest cases (4 manager + 1 bridge).

Bridge contract (matches the fork side, harmoniqs/opencode PR #118): DOWN open-bug-report {sessionID} / close-bug-report {sessionID}; UP bug-filed {sessionID, url} / bug-report-closed {sessionID} / bug-report-poke.

Preview-verified end-to-end: create → arm → open → dock renders; the poke heals the cold-boot lost-open race the dogfood hit.

Inert until the amicode_bug_report=1 boot param and the skills-bundle release (harmoniqs/amico-plugin#57 — deferred to post-merge by owner decision) align.

Opened by the develop DAG walk; marked ready for review with the release slice explicitly deferred.

…-param gate at every session prep (amicode#250)
…app boot (amicode#249 QA)
The app pokes once per frame boot with the flag on; the manager answers
with a fresh open-bug-report when a bug session is live (joining an
in-flight create, never double-creating), silence otherwise. Also: [bug]
lifecycle log lines for the open/poke paths — the preview debugging had
to spelunk the db for what one log line would have said.
…micode#249 QA)
The sync watch can surface a bug session orphaned by a dead extension
host. Closing that dock posted bug-report-closed for an id the new manager
never knew; dropping it left an immortal session the watch resurrected
forever. Unknown-id closes now read the session: bug_report metadata + not
archived → abort + hard delete; archived (filed) sessions and genuinely
foreign ids are never touched.
…election (amicode#249 QA)
The report-a-bug bridge command may now carry the composer's current
{providerID, modelID, variant}; the manager pins it on the arming command
(model: '<provider>/<model>') so the bug session runs the model the user
was actually using — subscription provider included (Zen never silently
becomes Go). Shape-validated at the bridge, bounded, stripped when
malformed; absent falls back to the server default.
…9 QA)
Two robustness gaps hit in the live preview dogfood:
- postToApp's retry timer threw 'Webview is disposed' when the chat
panel closed between the two posts (window closing mid-flow). The
down-lane now wraps both posts in try/catch — a lost open heals via
the app's boot poke + sync watch.
- A session closed while the bridge was down (disposed webview, dead
window) left manager.current pinned to a ghost: every later button
click would reveal nothing and never create. The reveal path now
probes session liveness (GET, 404-tolerant) before posting —
a dead memory clears itself and falls through to a fresh create.
… (amicode#249)
Cheap, fast, no OpenAI/Claude — the report-a-bug command now always
pins the arm to deepseek-v4-pro, bypassing the server default.
Aaron moved all skills into the extension (public) and armonissima
(internal) on main (PRs #258, #255). Our branch still carries the old
default roots, but this copy makes the skill available when the PR
merges — the extension's bundled ./skills dir is the first public root
on main.
…ode#249)
The 'Edit with notes' option requires the user to select it AND type
modifications in the 'Type your own answer' free-text field — the
question tool always appends this field as the last radio option.
Previous wording implied a separate textbox that doesn't exist.
…te (amicode#249)
The confirm step now asks via a plain free-form text question with no
pre-defined options, so the 'Type your own answer' field IS the only
input — always visible. Reply with 'file it', 'edit: <changes>', or
'veto' — the skill parses the answer.
…exactly (amicode#249)
The confirm step now uses the same 'Ask **one** question, via the `question`
tool' pattern as step 5, which the model follows reliably. Explicit 'Never
ask follow-ups' header prevents the model from inventing repo/comment
questions before the gate.
…ing pathway (amicode#249)
- Red/blue debug borders around the answer wrapper + question content —
proves the area renders; textarea is inside.
- The confirm gate gains a fourth option: 'comment: <repo>#<issue> <text>'
posts a clarifying comment to an existing issue via gh issue comment,
prints the sentinel, ends the session.
- createSession passes permission: [{question, deny, *}] — the question
tool is invisible to the model (hard guardrail, same as CLI non-interactive).
- Skill step 2 (capture) and step 6 (confirm gate): 'via the question tool'
replaced with 'output as plain text, wait for the user's reply.'
- Explicit 'Do not use the question tool' directive in both steps.
- Option A: at least one content question, accepts user follow-ups.
…omment path
- Sentinel is a lifecycle signal, not a semantic bug-classification
judgment. Prints after issue created, comment posted, OR chore filed.
- Comment path: explicit AMICODE_BUG_FILED format with full issue URL
(construct from repo + number).
- Removed 'actual filing' language that made the model skip the sentinel
for comments.
- Invariants updated: 'any successful GitHub action' replaces 'actual
filing'.
- armSession omits the model field entirely — the server uses whatever
model the user has configured globally (their defaultModel or the
server's built-in default).
- Removed findOriginModel (session.model isn't set by the model picker,
only at session create — so it's always empty for picker-users).
- No amicode.bugReportModel setting (unnecessary complexity).
@jeonghun-jj-lee
jeonghun-jj-leeforce-pushed the amico/issue-249-bug-report branch from b2033ae to bf11d7fCompareAugust 7, 2026 00:46
…eport
# Conflicts:
#	packages/extension/skills/report-a-bug/SKILL.md
#	packages/extension/src/chat_panel.ts
#	packages/extension/test/chat_bridge.test.ts
@jeonghun-jj-lee
jeonghun-jj-lee merged commit 00907b8 into mainAug 7, 2026
5 of 6 checks passed
gennadiryan pushed a commit that referenced this pull request Aug 7, 2026
jeonghun-jj-lee pushed a commit that referenced this pull request Aug 8, 2026
…opencode.lock): pin to v1.18.10-amicode.4 (#245) (#278)
Co-authored-by: Gennadi Ryan <gennadi@harmoniqs.co>
jeonghun-jj-lee pushed a commit that referenced this pull request Aug 8, 2026
)
* feat(extension): bug-session orchestration + lifecycle (#251), chore(opencode.lock): pin to v1.18.10-amicode.4 (#245)
* Adding provenance stamping to catch bad build configurations
* fix(extension): attribute detached builds in the provenance stamp
---------
Co-authored-by: Gennadi Ryan <gennadi@harmoniqs.co>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@jeonghun-jj-lee
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat(extension): bug-session orchestration + lifecycle (harmoniqs/amicode#249) - #251

Merged
jeonghun-jj-lee merged 24 commits into
mainfrom
amico/issue-249-bug-report
Aug 7, 2026
Merged

feat(extension): bug-session orchestration + lifecycle (harmoniqs/amicode#249)#251
jeonghun-jj-lee merged 24 commits into
mainfrom
amico/issue-249-bug-report

Conversation

@jeonghun-jj-lee

@jeonghun-jj-leejeonghun-jj-lee commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Part of #249 — the extension slice of the machine-managed bug-session feature. Lifecycle spec: docs/adr/0004-bug-session-lifecycle.md (on main).

Carries:

  • Orchestrate bug sessions from the extension: amicode.reportBug command, context envelope, lifecycle handler #250amicode.reportBug command, context envelope (bug_report session metadata), bridge allowlist additions, machine-managed lifecycle (filed → archive + close-bug-report; abandoned → abort + hard delete; failure → no orphans), single-open invariant, boot param re-pinned from the staged skill set.
  • QA fix (preview dogfood) — the bug-report-poke up-kind: relay Lane-1 admission, bridge route, and BugReportManager.poke() — re-posts open-bug-report when a bug session is live (joins an in-flight create, never double-creates), silence otherwise. Plus [bug] lifecycle log lines for the open/poke paths. 5 new vitest cases (4 manager + 1 bridge).

Bridge contract (matches the fork side, harmoniqs/opencode PR #118): DOWN open-bug-report {sessionID} / close-bug-report {sessionID}; UP bug-filed {sessionID, url} / bug-report-closed {sessionID} / bug-report-poke.

Preview-verified end-to-end: create → arm → open → dock renders; the poke heals the cold-boot lost-open race the dogfood hit.

Inert until the amicode_bug_report=1 boot param and the skills-bundle release (harmoniqs/amico-plugin#57 — deferred to post-merge by owner decision) align.

Opened by the develop DAG walk; marked ready for review with the release slice explicitly deferred.

…-param gate at every session prep (amicode#250)
…app boot (amicode#249 QA)
The app pokes once per frame boot with the flag on; the manager answers
with a fresh open-bug-report when a bug session is live (joining an
in-flight create, never double-creating), silence otherwise. Also: [bug]
lifecycle log lines for the open/poke paths — the preview debugging had
to spelunk the db for what one log line would have said.
…micode#249 QA)
The sync watch can surface a bug session orphaned by a dead extension
host. Closing that dock posted bug-report-closed for an id the new manager
never knew; dropping it left an immortal session the watch resurrected
forever. Unknown-id closes now read the session: bug_report metadata + not
archived → abort + hard delete; archived (filed) sessions and genuinely
foreign ids are never touched.
…election (amicode#249 QA)
The report-a-bug bridge command may now carry the composer's current
{providerID, modelID, variant}; the manager pins it on the arming command
(model: '<provider>/<model>') so the bug session runs the model the user
was actually using — subscription provider included (Zen never silently
becomes Go). Shape-validated at the bridge, bounded, stripped when
malformed; absent falls back to the server default.
…9 QA)
Two robustness gaps hit in the live preview dogfood:
- postToApp's retry timer threw 'Webview is disposed' when the chat
panel closed between the two posts (window closing mid-flow). The
down-lane now wraps both posts in try/catch — a lost open heals via
the app's boot poke + sync watch.
- A session closed while the bridge was down (disposed webview, dead
window) left manager.current pinned to a ghost: every later button
click would reveal nothing and never create. The reveal path now
probes session liveness (GET, 404-tolerant) before posting —
a dead memory clears itself and falls through to a fresh create.
… (amicode#249)
Cheap, fast, no OpenAI/Claude — the report-a-bug command now always
pins the arm to deepseek-v4-pro, bypassing the server default.
Aaron moved all skills into the extension (public) and armonissima
(internal) on main (PRs #258, #255). Our branch still carries the old
default roots, but this copy makes the skill available when the PR
merges — the extension's bundled ./skills dir is the first public root
on main.
…ode#249)
The 'Edit with notes' option requires the user to select it AND type
modifications in the 'Type your own answer' free-text field — the
question tool always appends this field as the last radio option.
Previous wording implied a separate textbox that doesn't exist.
…te (amicode#249)
The confirm step now asks via a plain free-form text question with no
pre-defined options, so the 'Type your own answer' field IS the only
input — always visible. Reply with 'file it', 'edit: <changes>', or
'veto' — the skill parses the answer.
…exactly (amicode#249)
The confirm step now uses the same 'Ask **one** question, via the `question`
tool' pattern as step 5, which the model follows reliably. Explicit 'Never
ask follow-ups' header prevents the model from inventing repo/comment
questions before the gate.
…ing pathway (amicode#249)
- Red/blue debug borders around the answer wrapper + question content —
proves the area renders; textarea is inside.
- The confirm gate gains a fourth option: 'comment: <repo>#<issue> <text>'
posts a clarifying comment to an existing issue via gh issue comment,
prints the sentinel, ends the session.
- createSession passes permission: [{question, deny, *}] — the question
tool is invisible to the model (hard guardrail, same as CLI non-interactive).
- Skill step 2 (capture) and step 6 (confirm gate): 'via the question tool'
replaced with 'output as plain text, wait for the user's reply.'
- Explicit 'Do not use the question tool' directive in both steps.
- Option A: at least one content question, accepts user follow-ups.
…omment path
- Sentinel is a lifecycle signal, not a semantic bug-classification
judgment. Prints after issue created, comment posted, OR chore filed.
- Comment path: explicit AMICODE_BUG_FILED format with full issue URL
(construct from repo + number).
- Removed 'actual filing' language that made the model skip the sentinel
for comments.
- Invariants updated: 'any successful GitHub action' replaces 'actual
filing'.
- armSession omits the model field entirely — the server uses whatever
model the user has configured globally (their defaultModel or the
server's built-in default).
- Removed findOriginModel (session.model isn't set by the model picker,
only at session create — so it's always empty for picker-users).
- No amicode.bugReportModel setting (unnecessary complexity).
@jeonghun-jj-lee
jeonghun-jj-leeforce-pushed the amico/issue-249-bug-report branch from b2033ae to bf11d7fCompareAugust 7, 2026 00:46
…eport
# Conflicts:
#	packages/extension/skills/report-a-bug/SKILL.md
#	packages/extension/src/chat_panel.ts
#	packages/extension/test/chat_bridge.test.ts
@jeonghun-jj-lee
jeonghun-jj-lee merged commit 00907b8 into mainAug 7, 2026
5 of 6 checks passed
gennadiryan pushed a commit that referenced this pull request Aug 7, 2026
jeonghun-jj-lee pushed a commit that referenced this pull request Aug 8, 2026
…opencode.lock): pin to v1.18.10-amicode.4 (#245) (#278)
Co-authored-by: Gennadi Ryan <gennadi@harmoniqs.co>
jeonghun-jj-lee pushed a commit that referenced this pull request Aug 8, 2026
)
* feat(extension): bug-session orchestration + lifecycle (#251), chore(opencode.lock): pin to v1.18.10-amicode.4 (#245)
* Adding provenance stamping to catch bad build configurations
* fix(extension): attribute detached builds in the provenance stamp
---------
Co-authored-by: Gennadi Ryan <gennadi@harmoniqs.co>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@jeonghun-jj-lee
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(extension): bug-session orchestration + lifecycle (harmoniqs/amicode#249) - #251

Merged
jeonghun-jj-lee merged 24 commits into
mainfrom
amico/issue-249-bug-report
Aug 7, 2026
Merged

feat(extension): bug-session orchestration + lifecycle (harmoniqs/amicode#249)#251
jeonghun-jj-lee merged 24 commits into
mainfrom
amico/issue-249-bug-report

Conversation

@jeonghun-jj-lee

@jeonghun-jj-leejeonghun-jj-lee commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Part of #249 — the extension slice of the machine-managed bug-session feature. Lifecycle spec: docs/adr/0004-bug-session-lifecycle.md (on main).

Carries:

  • Orchestrate bug sessions from the extension: amicode.reportBug command, context envelope, lifecycle handler #250amicode.reportBug command, context envelope (bug_report session metadata), bridge allowlist additions, machine-managed lifecycle (filed → archive + close-bug-report; abandoned → abort + hard delete; failure → no orphans), single-open invariant, boot param re-pinned from the staged skill set.
  • QA fix (preview dogfood) — the bug-report-poke up-kind: relay Lane-1 admission, bridge route, and BugReportManager.poke() — re-posts open-bug-report when a bug session is live (joins an in-flight create, never double-creates), silence otherwise. Plus [bug] lifecycle log lines for the open/poke paths. 5 new vitest cases (4 manager + 1 bridge).

Bridge contract (matches the fork side, harmoniqs/opencode PR #118): DOWN open-bug-report {sessionID} / close-bug-report {sessionID}; UP bug-filed {sessionID, url} / bug-report-closed {sessionID} / bug-report-poke.

Preview-verified end-to-end: create → arm → open → dock renders; the poke heals the cold-boot lost-open race the dogfood hit.

Inert until the amicode_bug_report=1 boot param and the skills-bundle release (harmoniqs/amico-plugin#57 — deferred to post-merge by owner decision) align.

Opened by the develop DAG walk; marked ready for review with the release slice explicitly deferred.

…-param gate at every session prep (amicode#250)
…app boot (amicode#249 QA)
The app pokes once per frame boot with the flag on; the manager answers
with a fresh open-bug-report when a bug session is live (joining an
in-flight create, never double-creating), silence otherwise. Also: [bug]
lifecycle log lines for the open/poke paths — the preview debugging had
to spelunk the db for what one log line would have said.
…micode#249 QA)
The sync watch can surface a bug session orphaned by a dead extension
host. Closing that dock posted bug-report-closed for an id the new manager
never knew; dropping it left an immortal session the watch resurrected
forever. Unknown-id closes now read the session: bug_report metadata + not
archived → abort + hard delete; archived (filed) sessions and genuinely
foreign ids are never touched.
…election (amicode#249 QA)
The report-a-bug bridge command may now carry the composer's current
{providerID, modelID, variant}; the manager pins it on the arming command
(model: '<provider>/<model>') so the bug session runs the model the user
was actually using — subscription provider included (Zen never silently
becomes Go). Shape-validated at the bridge, bounded, stripped when
malformed; absent falls back to the server default.
…9 QA)
Two robustness gaps hit in the live preview dogfood:
- postToApp's retry timer threw 'Webview is disposed' when the chat
panel closed between the two posts (window closing mid-flow). The
down-lane now wraps both posts in try/catch — a lost open heals via
the app's boot poke + sync watch.
- A session closed while the bridge was down (disposed webview, dead
window) left manager.current pinned to a ghost: every later button
click would reveal nothing and never create. The reveal path now
probes session liveness (GET, 404-tolerant) before posting —
a dead memory clears itself and falls through to a fresh create.
… (amicode#249)
Cheap, fast, no OpenAI/Claude — the report-a-bug command now always
pins the arm to deepseek-v4-pro, bypassing the server default.
Aaron moved all skills into the extension (public) and armonissima
(internal) on main (PRs #258, #255). Our branch still carries the old
default roots, but this copy makes the skill available when the PR
merges — the extension's bundled ./skills dir is the first public root
on main.
…ode#249)
The 'Edit with notes' option requires the user to select it AND type
modifications in the 'Type your own answer' free-text field — the
question tool always appends this field as the last radio option.
Previous wording implied a separate textbox that doesn't exist.
…te (amicode#249)
The confirm step now asks via a plain free-form text question with no
pre-defined options, so the 'Type your own answer' field IS the only
input — always visible. Reply with 'file it', 'edit: <changes>', or
'veto' — the skill parses the answer.
…exactly (amicode#249)
The confirm step now uses the same 'Ask **one** question, via the `question`
tool' pattern as step 5, which the model follows reliably. Explicit 'Never
ask follow-ups' header prevents the model from inventing repo/comment
questions before the gate.
…ing pathway (amicode#249)
- Red/blue debug borders around the answer wrapper + question content —
proves the area renders; textarea is inside.
- The confirm gate gains a fourth option: 'comment: <repo>#<issue> <text>'
posts a clarifying comment to an existing issue via gh issue comment,
prints the sentinel, ends the session.
- createSession passes permission: [{question, deny, *}] — the question
tool is invisible to the model (hard guardrail, same as CLI non-interactive).
- Skill step 2 (capture) and step 6 (confirm gate): 'via the question tool'
replaced with 'output as plain text, wait for the user's reply.'
- Explicit 'Do not use the question tool' directive in both steps.
- Option A: at least one content question, accepts user follow-ups.
…omment path
- Sentinel is a lifecycle signal, not a semantic bug-classification
judgment. Prints after issue created, comment posted, OR chore filed.
- Comment path: explicit AMICODE_BUG_FILED format with full issue URL
(construct from repo + number).
- Removed 'actual filing' language that made the model skip the sentinel
for comments.
- Invariants updated: 'any successful GitHub action' replaces 'actual
filing'.
- armSession omits the model field entirely — the server uses whatever
model the user has configured globally (their defaultModel or the
server's built-in default).
- Removed findOriginModel (session.model isn't set by the model picker,
only at session create — so it's always empty for picker-users).
- No amicode.bugReportModel setting (unnecessary complexity).
@jeonghun-jj-lee
jeonghun-jj-leeforce-pushed the amico/issue-249-bug-report branch from b2033ae to bf11d7fCompareAugust 7, 2026 00:46
…eport
# Conflicts:
#	packages/extension/skills/report-a-bug/SKILL.md
#	packages/extension/src/chat_panel.ts
#	packages/extension/test/chat_bridge.test.ts
@jeonghun-jj-lee
jeonghun-jj-lee merged commit 00907b8 into mainAug 7, 2026
5 of 6 checks passed
gennadiryan pushed a commit that referenced this pull request Aug 7, 2026
jeonghun-jj-lee pushed a commit that referenced this pull request Aug 8, 2026
…opencode.lock): pin to v1.18.10-amicode.4 (#245) (#278)
Co-authored-by: Gennadi Ryan <gennadi@harmoniqs.co>
jeonghun-jj-lee pushed a commit that referenced this pull request Aug 8, 2026
)
* feat(extension): bug-session orchestration + lifecycle (#251), chore(opencode.lock): pin to v1.18.10-amicode.4 (#245)
* Adding provenance stamping to catch bad build configurations
* fix(extension): attribute detached builds in the provenance stamp
---------
Co-authored-by: Gennadi Ryan <gennadi@harmoniqs.co>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@jeonghun-jj-lee
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(extension): bug-session orchestration + lifecycle (harmoniqs/amicode#249) - #251

Merged
jeonghun-jj-lee merged 24 commits into
mainfrom
amico/issue-249-bug-report
Aug 7, 2026
Merged

feat(extension): bug-session orchestration + lifecycle (harmoniqs/amicode#249)#251
jeonghun-jj-lee merged 24 commits into
mainfrom
amico/issue-249-bug-report

Conversation

@jeonghun-jj-lee

@jeonghun-jj-leejeonghun-jj-lee commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Part of #249 — the extension slice of the machine-managed bug-session feature. Lifecycle spec: docs/adr/0004-bug-session-lifecycle.md (on main).

Carries:

  • Orchestrate bug sessions from the extension: amicode.reportBug command, context envelope, lifecycle handler #250amicode.reportBug command, context envelope (bug_report session metadata), bridge allowlist additions, machine-managed lifecycle (filed → archive + close-bug-report; abandoned → abort + hard delete; failure → no orphans), single-open invariant, boot param re-pinned from the staged skill set.
  • QA fix (preview dogfood) — the bug-report-poke up-kind: relay Lane-1 admission, bridge route, and BugReportManager.poke() — re-posts open-bug-report when a bug session is live (joins an in-flight create, never double-creates), silence otherwise. Plus [bug] lifecycle log lines for the open/poke paths. 5 new vitest cases (4 manager + 1 bridge).

Bridge contract (matches the fork side, harmoniqs/opencode PR #118): DOWN open-bug-report {sessionID} / close-bug-report {sessionID}; UP bug-filed {sessionID, url} / bug-report-closed {sessionID} / bug-report-poke.

Preview-verified end-to-end: create → arm → open → dock renders; the poke heals the cold-boot lost-open race the dogfood hit.

Inert until the amicode_bug_report=1 boot param and the skills-bundle release (harmoniqs/amico-plugin#57 — deferred to post-merge by owner decision) align.

Opened by the develop DAG walk; marked ready for review with the release slice explicitly deferred.

…-param gate at every session prep (amicode#250)
…app boot (amicode#249 QA)
The app pokes once per frame boot with the flag on; the manager answers
with a fresh open-bug-report when a bug session is live (joining an
in-flight create, never double-creating), silence otherwise. Also: [bug]
lifecycle log lines for the open/poke paths — the preview debugging had
to spelunk the db for what one log line would have said.
…micode#249 QA)
The sync watch can surface a bug session orphaned by a dead extension
host. Closing that dock posted bug-report-closed for an id the new manager
never knew; dropping it left an immortal session the watch resurrected
forever. Unknown-id closes now read the session: bug_report metadata + not
archived → abort + hard delete; archived (filed) sessions and genuinely
foreign ids are never touched.
…election (amicode#249 QA)
The report-a-bug bridge command may now carry the composer's current
{providerID, modelID, variant}; the manager pins it on the arming command
(model: '<provider>/<model>') so the bug session runs the model the user
was actually using — subscription provider included (Zen never silently
becomes Go). Shape-validated at the bridge, bounded, stripped when
malformed; absent falls back to the server default.
…9 QA)
Two robustness gaps hit in the live preview dogfood:
- postToApp's retry timer threw 'Webview is disposed' when the chat
panel closed between the two posts (window closing mid-flow). The
down-lane now wraps both posts in try/catch — a lost open heals via
the app's boot poke + sync watch.
- A session closed while the bridge was down (disposed webview, dead
window) left manager.current pinned to a ghost: every later button
click would reveal nothing and never create. The reveal path now
probes session liveness (GET, 404-tolerant) before posting —
a dead memory clears itself and falls through to a fresh create.
… (amicode#249)
Cheap, fast, no OpenAI/Claude — the report-a-bug command now always
pins the arm to deepseek-v4-pro, bypassing the server default.
Aaron moved all skills into the extension (public) and armonissima
(internal) on main (PRs #258, #255). Our branch still carries the old
default roots, but this copy makes the skill available when the PR
merges — the extension's bundled ./skills dir is the first public root
on main.
…ode#249)
The 'Edit with notes' option requires the user to select it AND type
modifications in the 'Type your own answer' free-text field — the
question tool always appends this field as the last radio option.
Previous wording implied a separate textbox that doesn't exist.
…te (amicode#249)
The confirm step now asks via a plain free-form text question with no
pre-defined options, so the 'Type your own answer' field IS the only
input — always visible. Reply with 'file it', 'edit: <changes>', or
'veto' — the skill parses the answer.
…exactly (amicode#249)
The confirm step now uses the same 'Ask **one** question, via the `question`
tool' pattern as step 5, which the model follows reliably. Explicit 'Never
ask follow-ups' header prevents the model from inventing repo/comment
questions before the gate.
…ing pathway (amicode#249)
- Red/blue debug borders around the answer wrapper + question content —
proves the area renders; textarea is inside.
- The confirm gate gains a fourth option: 'comment: <repo>#<issue> <text>'
posts a clarifying comment to an existing issue via gh issue comment,
prints the sentinel, ends the session.
- createSession passes permission: [{question, deny, *}] — the question
tool is invisible to the model (hard guardrail, same as CLI non-interactive).
- Skill step 2 (capture) and step 6 (confirm gate): 'via the question tool'
replaced with 'output as plain text, wait for the user's reply.'
- Explicit 'Do not use the question tool' directive in both steps.
- Option A: at least one content question, accepts user follow-ups.
…omment path
- Sentinel is a lifecycle signal, not a semantic bug-classification
judgment. Prints after issue created, comment posted, OR chore filed.
- Comment path: explicit AMICODE_BUG_FILED format with full issue URL
(construct from repo + number).
- Removed 'actual filing' language that made the model skip the sentinel
for comments.
- Invariants updated: 'any successful GitHub action' replaces 'actual
filing'.
- armSession omits the model field entirely — the server uses whatever
model the user has configured globally (their defaultModel or the
server's built-in default).
- Removed findOriginModel (session.model isn't set by the model picker,
only at session create — so it's always empty for picker-users).
- No amicode.bugReportModel setting (unnecessary complexity).
@jeonghun-jj-lee
jeonghun-jj-leeforce-pushed the amico/issue-249-bug-report branch from b2033ae to bf11d7fCompareAugust 7, 2026 00:46
…eport
# Conflicts:
#	packages/extension/skills/report-a-bug/SKILL.md
#	packages/extension/src/chat_panel.ts
#	packages/extension/test/chat_bridge.test.ts
@jeonghun-jj-lee
jeonghun-jj-lee merged commit 00907b8 into mainAug 7, 2026
5 of 6 checks passed
gennadiryan pushed a commit that referenced this pull request Aug 7, 2026
jeonghun-jj-lee pushed a commit that referenced this pull request Aug 8, 2026
…opencode.lock): pin to v1.18.10-amicode.4 (#245) (#278)
Co-authored-by: Gennadi Ryan <gennadi@harmoniqs.co>
jeonghun-jj-lee pushed a commit that referenced this pull request Aug 8, 2026
)
* feat(extension): bug-session orchestration + lifecycle (#251), chore(opencode.lock): pin to v1.18.10-amicode.4 (#245)
* Adding provenance stamping to catch bad build configurations
* fix(extension): attribute detached builds in the provenance stamp
---------
Co-authored-by: Gennadi Ryan <gennadi@harmoniqs.co>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@jeonghun-jj-lee
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat(extension): bug-session orchestration + lifecycle (harmoniqs/amicode#249) - #251

Merged
jeonghun-jj-lee merged 24 commits into
mainfrom
amico/issue-249-bug-report
Aug 7, 2026
Merged

feat(extension): bug-session orchestration + lifecycle (harmoniqs/amicode#249)#251
jeonghun-jj-lee merged 24 commits into
mainfrom
amico/issue-249-bug-report

Conversation

@jeonghun-jj-lee

@jeonghun-jj-leejeonghun-jj-lee commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Part of #249 — the extension slice of the machine-managed bug-session feature. Lifecycle spec: docs/adr/0004-bug-session-lifecycle.md (on main).

Carries:

  • Orchestrate bug sessions from the extension: amicode.reportBug command, context envelope, lifecycle handler #250amicode.reportBug command, context envelope (bug_report session metadata), bridge allowlist additions, machine-managed lifecycle (filed → archive + close-bug-report; abandoned → abort + hard delete; failure → no orphans), single-open invariant, boot param re-pinned from the staged skill set.
  • QA fix (preview dogfood) — the bug-report-poke up-kind: relay Lane-1 admission, bridge route, and BugReportManager.poke() — re-posts open-bug-report when a bug session is live (joins an in-flight create, never double-creates), silence otherwise. Plus [bug] lifecycle log lines for the open/poke paths. 5 new vitest cases (4 manager + 1 bridge).

Bridge contract (matches the fork side, harmoniqs/opencode PR #118): DOWN open-bug-report {sessionID} / close-bug-report {sessionID}; UP bug-filed {sessionID, url} / bug-report-closed {sessionID} / bug-report-poke.

Preview-verified end-to-end: create → arm → open → dock renders; the poke heals the cold-boot lost-open race the dogfood hit.

Inert until the amicode_bug_report=1 boot param and the skills-bundle release (harmoniqs/amico-plugin#57 — deferred to post-merge by owner decision) align.

Opened by the develop DAG walk; marked ready for review with the release slice explicitly deferred.

…-param gate at every session prep (amicode#250)
…app boot (amicode#249 QA)
The app pokes once per frame boot with the flag on; the manager answers
with a fresh open-bug-report when a bug session is live (joining an
in-flight create, never double-creating), silence otherwise. Also: [bug]
lifecycle log lines for the open/poke paths — the preview debugging had
to spelunk the db for what one log line would have said.
…micode#249 QA)
The sync watch can surface a bug session orphaned by a dead extension
host. Closing that dock posted bug-report-closed for an id the new manager
never knew; dropping it left an immortal session the watch resurrected
forever. Unknown-id closes now read the session: bug_report metadata + not
archived → abort + hard delete; archived (filed) sessions and genuinely
foreign ids are never touched.
…election (amicode#249 QA)
The report-a-bug bridge command may now carry the composer's current
{providerID, modelID, variant}; the manager pins it on the arming command
(model: '<provider>/<model>') so the bug session runs the model the user
was actually using — subscription provider included (Zen never silently
becomes Go). Shape-validated at the bridge, bounded, stripped when
malformed; absent falls back to the server default.
…9 QA)
Two robustness gaps hit in the live preview dogfood:
- postToApp's retry timer threw 'Webview is disposed' when the chat
panel closed between the two posts (window closing mid-flow). The
down-lane now wraps both posts in try/catch — a lost open heals via
the app's boot poke + sync watch.
- A session closed while the bridge was down (disposed webview, dead
window) left manager.current pinned to a ghost: every later button
click would reveal nothing and never create. The reveal path now
probes session liveness (GET, 404-tolerant) before posting —
a dead memory clears itself and falls through to a fresh create.
… (amicode#249)
Cheap, fast, no OpenAI/Claude — the report-a-bug command now always
pins the arm to deepseek-v4-pro, bypassing the server default.
Aaron moved all skills into the extension (public) and armonissima
(internal) on main (PRs #258, #255). Our branch still carries the old
default roots, but this copy makes the skill available when the PR
merges — the extension's bundled ./skills dir is the first public root
on main.
…ode#249)
The 'Edit with notes' option requires the user to select it AND type
modifications in the 'Type your own answer' free-text field — the
question tool always appends this field as the last radio option.
Previous wording implied a separate textbox that doesn't exist.
…te (amicode#249)
The confirm step now asks via a plain free-form text question with no
pre-defined options, so the 'Type your own answer' field IS the only
input — always visible. Reply with 'file it', 'edit: <changes>', or
'veto' — the skill parses the answer.
…exactly (amicode#249)
The confirm step now uses the same 'Ask **one** question, via the `question`
tool' pattern as step 5, which the model follows reliably. Explicit 'Never
ask follow-ups' header prevents the model from inventing repo/comment
questions before the gate.
…ing pathway (amicode#249)
- Red/blue debug borders around the answer wrapper + question content —
proves the area renders; textarea is inside.
- The confirm gate gains a fourth option: 'comment: <repo>#<issue> <text>'
posts a clarifying comment to an existing issue via gh issue comment,
prints the sentinel, ends the session.
- createSession passes permission: [{question, deny, *}] — the question
tool is invisible to the model (hard guardrail, same as CLI non-interactive).
- Skill step 2 (capture) and step 6 (confirm gate): 'via the question tool'
replaced with 'output as plain text, wait for the user's reply.'
- Explicit 'Do not use the question tool' directive in both steps.
- Option A: at least one content question, accepts user follow-ups.
…omment path
- Sentinel is a lifecycle signal, not a semantic bug-classification
judgment. Prints after issue created, comment posted, OR chore filed.
- Comment path: explicit AMICODE_BUG_FILED format with full issue URL
(construct from repo + number).
- Removed 'actual filing' language that made the model skip the sentinel
for comments.
- Invariants updated: 'any successful GitHub action' replaces 'actual
filing'.
- armSession omits the model field entirely — the server uses whatever
model the user has configured globally (their defaultModel or the
server's built-in default).
- Removed findOriginModel (session.model isn't set by the model picker,
only at session create — so it's always empty for picker-users).
- No amicode.bugReportModel setting (unnecessary complexity).
@jeonghun-jj-lee
jeonghun-jj-leeforce-pushed the amico/issue-249-bug-report branch from b2033ae to bf11d7fCompareAugust 7, 2026 00:46
…eport
# Conflicts:
#	packages/extension/skills/report-a-bug/SKILL.md
#	packages/extension/src/chat_panel.ts
#	packages/extension/test/chat_bridge.test.ts
@jeonghun-jj-lee
jeonghun-jj-lee merged commit 00907b8 into mainAug 7, 2026
5 of 6 checks passed
gennadiryan pushed a commit that referenced this pull request Aug 7, 2026
jeonghun-jj-lee pushed a commit that referenced this pull request Aug 8, 2026
…opencode.lock): pin to v1.18.10-amicode.4 (#245) (#278)
Co-authored-by: Gennadi Ryan <gennadi@harmoniqs.co>
jeonghun-jj-lee pushed a commit that referenced this pull request Aug 8, 2026
)
* feat(extension): bug-session orchestration + lifecycle (#251), chore(opencode.lock): pin to v1.18.10-amicode.4 (#245)
* Adding provenance stamping to catch bad build configurations
* fix(extension): attribute detached builds in the provenance stamp
---------
Co-authored-by: Gennadi Ryan <gennadi@harmoniqs.co>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@jeonghun-jj-lee
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(extension): bug-session orchestration + lifecycle (harmoniqs/amicode#249) - #251

Merged
jeonghun-jj-lee merged 24 commits into
mainfrom
amico/issue-249-bug-report
Aug 7, 2026
Merged

feat(extension): bug-session orchestration + lifecycle (harmoniqs/amicode#249)#251
jeonghun-jj-lee merged 24 commits into
mainfrom
amico/issue-249-bug-report

Conversation

@jeonghun-jj-lee

@jeonghun-jj-leejeonghun-jj-lee commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Part of #249 — the extension slice of the machine-managed bug-session feature. Lifecycle spec: docs/adr/0004-bug-session-lifecycle.md (on main).

Carries:

  • Orchestrate bug sessions from the extension: amicode.reportBug command, context envelope, lifecycle handler #250amicode.reportBug command, context envelope (bug_report session metadata), bridge allowlist additions, machine-managed lifecycle (filed → archive + close-bug-report; abandoned → abort + hard delete; failure → no orphans), single-open invariant, boot param re-pinned from the staged skill set.
  • QA fix (preview dogfood) — the bug-report-poke up-kind: relay Lane-1 admission, bridge route, and BugReportManager.poke() — re-posts open-bug-report when a bug session is live (joins an in-flight create, never double-creates), silence otherwise. Plus [bug] lifecycle log lines for the open/poke paths. 5 new vitest cases (4 manager + 1 bridge).

Bridge contract (matches the fork side, harmoniqs/opencode PR #118): DOWN open-bug-report {sessionID} / close-bug-report {sessionID}; UP bug-filed {sessionID, url} / bug-report-closed {sessionID} / bug-report-poke.

Preview-verified end-to-end: create → arm → open → dock renders; the poke heals the cold-boot lost-open race the dogfood hit.

Inert until the amicode_bug_report=1 boot param and the skills-bundle release (harmoniqs/amico-plugin#57 — deferred to post-merge by owner decision) align.

Opened by the develop DAG walk; marked ready for review with the release slice explicitly deferred.

…-param gate at every session prep (amicode#250)
…app boot (amicode#249 QA)
The app pokes once per frame boot with the flag on; the manager answers
with a fresh open-bug-report when a bug session is live (joining an
in-flight create, never double-creating), silence otherwise. Also: [bug]
lifecycle log lines for the open/poke paths — the preview debugging had
to spelunk the db for what one log line would have said.
…micode#249 QA)
The sync watch can surface a bug session orphaned by a dead extension
host. Closing that dock posted bug-report-closed for an id the new manager
never knew; dropping it left an immortal session the watch resurrected
forever. Unknown-id closes now read the session: bug_report metadata + not
archived → abort + hard delete; archived (filed) sessions and genuinely
foreign ids are never touched.
…election (amicode#249 QA)
The report-a-bug bridge command may now carry the composer's current
{providerID, modelID, variant}; the manager pins it on the arming command
(model: '<provider>/<model>') so the bug session runs the model the user
was actually using — subscription provider included (Zen never silently
becomes Go). Shape-validated at the bridge, bounded, stripped when
malformed; absent falls back to the server default.
…9 QA)
Two robustness gaps hit in the live preview dogfood:
- postToApp's retry timer threw 'Webview is disposed' when the chat
panel closed between the two posts (window closing mid-flow). The
down-lane now wraps both posts in try/catch — a lost open heals via
the app's boot poke + sync watch.
- A session closed while the bridge was down (disposed webview, dead
window) left manager.current pinned to a ghost: every later button
click would reveal nothing and never create. The reveal path now
probes session liveness (GET, 404-tolerant) before posting —
a dead memory clears itself and falls through to a fresh create.
… (amicode#249)
Cheap, fast, no OpenAI/Claude — the report-a-bug command now always
pins the arm to deepseek-v4-pro, bypassing the server default.
Aaron moved all skills into the extension (public) and armonissima
(internal) on main (PRs #258, #255). Our branch still carries the old
default roots, but this copy makes the skill available when the PR
merges — the extension's bundled ./skills dir is the first public root
on main.
…ode#249)
The 'Edit with notes' option requires the user to select it AND type
modifications in the 'Type your own answer' free-text field — the
question tool always appends this field as the last radio option.
Previous wording implied a separate textbox that doesn't exist.
…te (amicode#249)
The confirm step now asks via a plain free-form text question with no
pre-defined options, so the 'Type your own answer' field IS the only
input — always visible. Reply with 'file it', 'edit: <changes>', or
'veto' — the skill parses the answer.
…exactly (amicode#249)
The confirm step now uses the same 'Ask **one** question, via the `question`
tool' pattern as step 5, which the model follows reliably. Explicit 'Never
ask follow-ups' header prevents the model from inventing repo/comment
questions before the gate.
…ing pathway (amicode#249)
- Red/blue debug borders around the answer wrapper + question content —
proves the area renders; textarea is inside.
- The confirm gate gains a fourth option: 'comment: <repo>#<issue> <text>'
posts a clarifying comment to an existing issue via gh issue comment,
prints the sentinel, ends the session.
- createSession passes permission: [{question, deny, *}] — the question
tool is invisible to the model (hard guardrail, same as CLI non-interactive).
- Skill step 2 (capture) and step 6 (confirm gate): 'via the question tool'
replaced with 'output as plain text, wait for the user's reply.'
- Explicit 'Do not use the question tool' directive in both steps.
- Option A: at least one content question, accepts user follow-ups.
…omment path
- Sentinel is a lifecycle signal, not a semantic bug-classification
judgment. Prints after issue created, comment posted, OR chore filed.
- Comment path: explicit AMICODE_BUG_FILED format with full issue URL
(construct from repo + number).
- Removed 'actual filing' language that made the model skip the sentinel
for comments.
- Invariants updated: 'any successful GitHub action' replaces 'actual
filing'.
- armSession omits the model field entirely — the server uses whatever
model the user has configured globally (their defaultModel or the
server's built-in default).
- Removed findOriginModel (session.model isn't set by the model picker,
only at session create — so it's always empty for picker-users).
- No amicode.bugReportModel setting (unnecessary complexity).
@jeonghun-jj-lee
jeonghun-jj-leeforce-pushed the amico/issue-249-bug-report branch from b2033ae to bf11d7fCompareAugust 7, 2026 00:46
…eport
# Conflicts:
#	packages/extension/skills/report-a-bug/SKILL.md
#	packages/extension/src/chat_panel.ts
#	packages/extension/test/chat_bridge.test.ts
@jeonghun-jj-lee
jeonghun-jj-lee merged commit 00907b8 into mainAug 7, 2026
5 of 6 checks passed
gennadiryan pushed a commit that referenced this pull request Aug 7, 2026
jeonghun-jj-lee pushed a commit that referenced this pull request Aug 8, 2026
…opencode.lock): pin to v1.18.10-amicode.4 (#245) (#278)
Co-authored-by: Gennadi Ryan <gennadi@harmoniqs.co>
jeonghun-jj-lee pushed a commit that referenced this pull request Aug 8, 2026
)
* feat(extension): bug-session orchestration + lifecycle (#251), chore(opencode.lock): pin to v1.18.10-amicode.4 (#245)
* Adding provenance stamping to catch bad build configurations
* fix(extension): attribute detached builds in the provenance stamp
---------
Co-authored-by: Gennadi Ryan <gennadi@harmoniqs.co>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@jeonghun-jj-lee
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(extension): bug-session orchestration + lifecycle (harmoniqs/amicode#249) - #251

Merged
jeonghun-jj-lee merged 24 commits into
mainfrom
amico/issue-249-bug-report
Aug 7, 2026
Merged

feat(extension): bug-session orchestration + lifecycle (harmoniqs/amicode#249)#251
jeonghun-jj-lee merged 24 commits into
mainfrom
amico/issue-249-bug-report

Conversation

@jeonghun-jj-lee

@jeonghun-jj-leejeonghun-jj-lee commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Part of #249 — the extension slice of the machine-managed bug-session feature. Lifecycle spec: docs/adr/0004-bug-session-lifecycle.md (on main).

Carries:

  • Orchestrate bug sessions from the extension: amicode.reportBug command, context envelope, lifecycle handler #250amicode.reportBug command, context envelope (bug_report session metadata), bridge allowlist additions, machine-managed lifecycle (filed → archive + close-bug-report; abandoned → abort + hard delete; failure → no orphans), single-open invariant, boot param re-pinned from the staged skill set.
  • QA fix (preview dogfood) — the bug-report-poke up-kind: relay Lane-1 admission, bridge route, and BugReportManager.poke() — re-posts open-bug-report when a bug session is live (joins an in-flight create, never double-creates), silence otherwise. Plus [bug] lifecycle log lines for the open/poke paths. 5 new vitest cases (4 manager + 1 bridge).

Bridge contract (matches the fork side, harmoniqs/opencode PR #118): DOWN open-bug-report {sessionID} / close-bug-report {sessionID}; UP bug-filed {sessionID, url} / bug-report-closed {sessionID} / bug-report-poke.

Preview-verified end-to-end: create → arm → open → dock renders; the poke heals the cold-boot lost-open race the dogfood hit.

Inert until the amicode_bug_report=1 boot param and the skills-bundle release (harmoniqs/amico-plugin#57 — deferred to post-merge by owner decision) align.

Opened by the develop DAG walk; marked ready for review with the release slice explicitly deferred.

…-param gate at every session prep (amicode#250)
…app boot (amicode#249 QA)
The app pokes once per frame boot with the flag on; the manager answers
with a fresh open-bug-report when a bug session is live (joining an
in-flight create, never double-creating), silence otherwise. Also: [bug]
lifecycle log lines for the open/poke paths — the preview debugging had
to spelunk the db for what one log line would have said.
…micode#249 QA)
The sync watch can surface a bug session orphaned by a dead extension
host. Closing that dock posted bug-report-closed for an id the new manager
never knew; dropping it left an immortal session the watch resurrected
forever. Unknown-id closes now read the session: bug_report metadata + not
archived → abort + hard delete; archived (filed) sessions and genuinely
foreign ids are never touched.
…election (amicode#249 QA)
The report-a-bug bridge command may now carry the composer's current
{providerID, modelID, variant}; the manager pins it on the arming command
(model: '<provider>/<model>') so the bug session runs the model the user
was actually using — subscription provider included (Zen never silently
becomes Go). Shape-validated at the bridge, bounded, stripped when
malformed; absent falls back to the server default.
…9 QA)
Two robustness gaps hit in the live preview dogfood:
- postToApp's retry timer threw 'Webview is disposed' when the chat
panel closed between the two posts (window closing mid-flow). The
down-lane now wraps both posts in try/catch — a lost open heals via
the app's boot poke + sync watch.
- A session closed while the bridge was down (disposed webview, dead
window) left manager.current pinned to a ghost: every later button
click would reveal nothing and never create. The reveal path now
probes session liveness (GET, 404-tolerant) before posting —
a dead memory clears itself and falls through to a fresh create.
… (amicode#249)
Cheap, fast, no OpenAI/Claude — the report-a-bug command now always
pins the arm to deepseek-v4-pro, bypassing the server default.
Aaron moved all skills into the extension (public) and armonissima
(internal) on main (PRs #258, #255). Our branch still carries the old
default roots, but this copy makes the skill available when the PR
merges — the extension's bundled ./skills dir is the first public root
on main.
…ode#249)
The 'Edit with notes' option requires the user to select it AND type
modifications in the 'Type your own answer' free-text field — the
question tool always appends this field as the last radio option.
Previous wording implied a separate textbox that doesn't exist.
…te (amicode#249)
The confirm step now asks via a plain free-form text question with no
pre-defined options, so the 'Type your own answer' field IS the only
input — always visible. Reply with 'file it', 'edit: <changes>', or
'veto' — the skill parses the answer.
…exactly (amicode#249)
The confirm step now uses the same 'Ask **one** question, via the `question`
tool' pattern as step 5, which the model follows reliably. Explicit 'Never
ask follow-ups' header prevents the model from inventing repo/comment
questions before the gate.
…ing pathway (amicode#249)
- Red/blue debug borders around the answer wrapper + question content —
proves the area renders; textarea is inside.
- The confirm gate gains a fourth option: 'comment: <repo>#<issue> <text>'
posts a clarifying comment to an existing issue via gh issue comment,
prints the sentinel, ends the session.
- createSession passes permission: [{question, deny, *}] — the question
tool is invisible to the model (hard guardrail, same as CLI non-interactive).
- Skill step 2 (capture) and step 6 (confirm gate): 'via the question tool'
replaced with 'output as plain text, wait for the user's reply.'
- Explicit 'Do not use the question tool' directive in both steps.
- Option A: at least one content question, accepts user follow-ups.
…omment path
- Sentinel is a lifecycle signal, not a semantic bug-classification
judgment. Prints after issue created, comment posted, OR chore filed.
- Comment path: explicit AMICODE_BUG_FILED format with full issue URL
(construct from repo + number).
- Removed 'actual filing' language that made the model skip the sentinel
for comments.
- Invariants updated: 'any successful GitHub action' replaces 'actual
filing'.
- armSession omits the model field entirely — the server uses whatever
model the user has configured globally (their defaultModel or the
server's built-in default).
- Removed findOriginModel (session.model isn't set by the model picker,
only at session create — so it's always empty for picker-users).
- No amicode.bugReportModel setting (unnecessary complexity).
@jeonghun-jj-lee
jeonghun-jj-leeforce-pushed the amico/issue-249-bug-report branch from b2033ae to bf11d7fCompareAugust 7, 2026 00:46
…eport
# Conflicts:
#	packages/extension/skills/report-a-bug/SKILL.md
#	packages/extension/src/chat_panel.ts
#	packages/extension/test/chat_bridge.test.ts
@jeonghun-jj-lee
jeonghun-jj-lee merged commit 00907b8 into mainAug 7, 2026
5 of 6 checks passed
gennadiryan pushed a commit that referenced this pull request Aug 7, 2026
jeonghun-jj-lee pushed a commit that referenced this pull request Aug 8, 2026
…opencode.lock): pin to v1.18.10-amicode.4 (#245) (#278)
Co-authored-by: Gennadi Ryan <gennadi@harmoniqs.co>
jeonghun-jj-lee pushed a commit that referenced this pull request Aug 8, 2026
)
* feat(extension): bug-session orchestration + lifecycle (#251), chore(opencode.lock): pin to v1.18.10-amicode.4 (#245)
* Adding provenance stamping to catch bad build configurations
* fix(extension): attribute detached builds in the provenance stamp
---------
Co-authored-by: Gennadi Ryan <gennadi@harmoniqs.co>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@jeonghun-jj-lee
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat(extension): bug-session orchestration + lifecycle (harmoniqs/amicode#249) - #251

Merged
jeonghun-jj-lee merged 24 commits into
mainfrom
amico/issue-249-bug-report
Aug 7, 2026
Merged

feat(extension): bug-session orchestration + lifecycle (harmoniqs/amicode#249)#251
jeonghun-jj-lee merged 24 commits into
mainfrom
amico/issue-249-bug-report

Conversation

@jeonghun-jj-lee

@jeonghun-jj-leejeonghun-jj-lee commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Part of #249 — the extension slice of the machine-managed bug-session feature. Lifecycle spec: docs/adr/0004-bug-session-lifecycle.md (on main).

Carries:

  • Orchestrate bug sessions from the extension: amicode.reportBug command, context envelope, lifecycle handler #250amicode.reportBug command, context envelope (bug_report session metadata), bridge allowlist additions, machine-managed lifecycle (filed → archive + close-bug-report; abandoned → abort + hard delete; failure → no orphans), single-open invariant, boot param re-pinned from the staged skill set.
  • QA fix (preview dogfood) — the bug-report-poke up-kind: relay Lane-1 admission, bridge route, and BugReportManager.poke() — re-posts open-bug-report when a bug session is live (joins an in-flight create, never double-creates), silence otherwise. Plus [bug] lifecycle log lines for the open/poke paths. 5 new vitest cases (4 manager + 1 bridge).

Bridge contract (matches the fork side, harmoniqs/opencode PR #118): DOWN open-bug-report {sessionID} / close-bug-report {sessionID}; UP bug-filed {sessionID, url} / bug-report-closed {sessionID} / bug-report-poke.

Preview-verified end-to-end: create → arm → open → dock renders; the poke heals the cold-boot lost-open race the dogfood hit.

Inert until the amicode_bug_report=1 boot param and the skills-bundle release (harmoniqs/amico-plugin#57 — deferred to post-merge by owner decision) align.

Opened by the develop DAG walk; marked ready for review with the release slice explicitly deferred.

…-param gate at every session prep (amicode#250)
…app boot (amicode#249 QA)
The app pokes once per frame boot with the flag on; the manager answers
with a fresh open-bug-report when a bug session is live (joining an
in-flight create, never double-creating), silence otherwise. Also: [bug]
lifecycle log lines for the open/poke paths — the preview debugging had
to spelunk the db for what one log line would have said.
…micode#249 QA)
The sync watch can surface a bug session orphaned by a dead extension
host. Closing that dock posted bug-report-closed for an id the new manager
never knew; dropping it left an immortal session the watch resurrected
forever. Unknown-id closes now read the session: bug_report metadata + not
archived → abort + hard delete; archived (filed) sessions and genuinely
foreign ids are never touched.
…election (amicode#249 QA)
The report-a-bug bridge command may now carry the composer's current
{providerID, modelID, variant}; the manager pins it on the arming command
(model: '<provider>/<model>') so the bug session runs the model the user
was actually using — subscription provider included (Zen never silently
becomes Go). Shape-validated at the bridge, bounded, stripped when
malformed; absent falls back to the server default.
…9 QA)
Two robustness gaps hit in the live preview dogfood:
- postToApp's retry timer threw 'Webview is disposed' when the chat
panel closed between the two posts (window closing mid-flow). The
down-lane now wraps both posts in try/catch — a lost open heals via
the app's boot poke + sync watch.
- A session closed while the bridge was down (disposed webview, dead
window) left manager.current pinned to a ghost: every later button
click would reveal nothing and never create. The reveal path now
probes session liveness (GET, 404-tolerant) before posting —
a dead memory clears itself and falls through to a fresh create.
… (amicode#249)
Cheap, fast, no OpenAI/Claude — the report-a-bug command now always
pins the arm to deepseek-v4-pro, bypassing the server default.
Aaron moved all skills into the extension (public) and armonissima
(internal) on main (PRs #258, #255). Our branch still carries the old
default roots, but this copy makes the skill available when the PR
merges — the extension's bundled ./skills dir is the first public root
on main.
…ode#249)
The 'Edit with notes' option requires the user to select it AND type
modifications in the 'Type your own answer' free-text field — the
question tool always appends this field as the last radio option.
Previous wording implied a separate textbox that doesn't exist.
…te (amicode#249)
The confirm step now asks via a plain free-form text question with no
pre-defined options, so the 'Type your own answer' field IS the only
input — always visible. Reply with 'file it', 'edit: <changes>', or
'veto' — the skill parses the answer.
…exactly (amicode#249)
The confirm step now uses the same 'Ask **one** question, via the `question`
tool' pattern as step 5, which the model follows reliably. Explicit 'Never
ask follow-ups' header prevents the model from inventing repo/comment
questions before the gate.
…ing pathway (amicode#249)
- Red/blue debug borders around the answer wrapper + question content —
proves the area renders; textarea is inside.
- The confirm gate gains a fourth option: 'comment: <repo>#<issue> <text>'
posts a clarifying comment to an existing issue via gh issue comment,
prints the sentinel, ends the session.
- createSession passes permission: [{question, deny, *}] — the question
tool is invisible to the model (hard guardrail, same as CLI non-interactive).
- Skill step 2 (capture) and step 6 (confirm gate): 'via the question tool'
replaced with 'output as plain text, wait for the user's reply.'
- Explicit 'Do not use the question tool' directive in both steps.
- Option A: at least one content question, accepts user follow-ups.
…omment path
- Sentinel is a lifecycle signal, not a semantic bug-classification
judgment. Prints after issue created, comment posted, OR chore filed.
- Comment path: explicit AMICODE_BUG_FILED format with full issue URL
(construct from repo + number).
- Removed 'actual filing' language that made the model skip the sentinel
for comments.
- Invariants updated: 'any successful GitHub action' replaces 'actual
filing'.
- armSession omits the model field entirely — the server uses whatever
model the user has configured globally (their defaultModel or the
server's built-in default).
- Removed findOriginModel (session.model isn't set by the model picker,
only at session create — so it's always empty for picker-users).
- No amicode.bugReportModel setting (unnecessary complexity).
@jeonghun-jj-lee
jeonghun-jj-leeforce-pushed the amico/issue-249-bug-report branch from b2033ae to bf11d7fCompareAugust 7, 2026 00:46
…eport
# Conflicts:
#	packages/extension/skills/report-a-bug/SKILL.md
#	packages/extension/src/chat_panel.ts
#	packages/extension/test/chat_bridge.test.ts
@jeonghun-jj-lee
jeonghun-jj-lee merged commit 00907b8 into mainAug 7, 2026
5 of 6 checks passed
gennadiryan pushed a commit that referenced this pull request Aug 7, 2026
jeonghun-jj-lee pushed a commit that referenced this pull request Aug 8, 2026
…opencode.lock): pin to v1.18.10-amicode.4 (#245) (#278)
Co-authored-by: Gennadi Ryan <gennadi@harmoniqs.co>
jeonghun-jj-lee pushed a commit that referenced this pull request Aug 8, 2026
)
* feat(extension): bug-session orchestration + lifecycle (#251), chore(opencode.lock): pin to v1.18.10-amicode.4 (#245)
* Adding provenance stamping to catch bad build configurations
* fix(extension): attribute detached builds in the provenance stamp
---------
Co-authored-by: Gennadi Ryan <gennadi@harmoniqs.co>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@jeonghun-jj-lee