codehere 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/README.md +36 -192
  2. package/dist/application/use-cases/check-claimed-tests.js +81 -0
  3. package/dist/application/use-cases/detect-test-weakening.js +237 -0
  4. package/dist/application/use-cases/rerun-tests.js +110 -7
  5. package/dist/index.js +38 -1212
  6. package/dist/infrastructure/orchestration/artifacts-extractor.js +2 -323
  7. package/dist/presentation/cli/commands/check-command.js +178 -23
  8. package/dist/presentation/cli/commands/help-command.js +21 -285
  9. package/dist/ui.js +5 -236
  10. package/dist/utils/version.js +0 -6
  11. package/package.json +9 -38
  12. package/dist/application/services/verdict-service.js +0 -154
  13. package/dist/application/use-cases/assess-cross-vendor.js +0 -126
  14. package/dist/application/use-cases/build-cross-vendor-verdict.js +0 -118
  15. package/dist/application/use-cases/domain-trust.js +0 -110
  16. package/dist/application/use-cases/export-aat.js +0 -107
  17. package/dist/application/use-cases/generate-acceptance-criteria.js +0 -223
  18. package/dist/application/use-cases/generate-final-report.js +0 -259
  19. package/dist/application/use-cases/generate-narration.js +0 -130
  20. package/dist/application/use-cases/generate-thread-title.js +0 -181
  21. package/dist/application/use-cases/narrator-prompt-template.js +0 -158
  22. package/dist/application/use-cases/plan-auto-review.js +0 -57
  23. package/dist/application/use-cases/reconcile-audit.js +0 -100
  24. package/dist/application/use-cases/search-sessions.js +0 -70
  25. package/dist/application/use-cases/should-auto-review.js +0 -71
  26. package/dist/application/use-cases/thread-export.js +0 -245
  27. package/dist/application/use-cases/verify-claim.js +0 -456
  28. package/dist/application/use-cases/write-pass.js +0 -277
  29. package/dist/domain/audit.js +0 -11
  30. package/dist/domain/services/codebase-detector.js +0 -85
  31. package/dist/domain/task.js +0 -91
  32. package/dist/error-handler.js +0 -139
  33. package/dist/infrastructure/completion/bash-completion.js +0 -29
  34. package/dist/infrastructure/completion/fish-completion.js +0 -17
  35. package/dist/infrastructure/completion/zsh-completion.js +0 -25
  36. package/dist/infrastructure/config/config-manager.js +0 -174
  37. package/dist/infrastructure/config/product-context.js +0 -49
  38. package/dist/infrastructure/context/adapters/drawio-source.js +0 -157
  39. package/dist/infrastructure/context/adapters/figma-source.js +0 -198
  40. package/dist/infrastructure/context/adapters/github-issue-source.js +0 -160
  41. package/dist/infrastructure/context/adapters/linear-source.js +0 -190
  42. package/dist/infrastructure/context/context-resolver.js +0 -144
  43. package/dist/infrastructure/context/context-source.js +0 -114
  44. package/dist/infrastructure/context/github-api.js +0 -110
  45. package/dist/infrastructure/context/github-device-flow.js +0 -65
  46. package/dist/infrastructure/context/oauth-flow.js +0 -207
  47. package/dist/infrastructure/context/oauth-store.js +0 -122
  48. package/dist/infrastructure/context/registry-bootstrap.js +0 -95
  49. package/dist/infrastructure/context/write-pass-resolver.js +0 -106
  50. package/dist/infrastructure/cost/budget-config.js +0 -114
  51. package/dist/infrastructure/cost/cost-router.js +0 -97
  52. package/dist/infrastructure/cost/spend-aggregator.js +0 -222
  53. package/dist/infrastructure/cost/team-ledger.js +0 -355
  54. package/dist/infrastructure/discovery/discovery-log.js +0 -85
  55. package/dist/infrastructure/hooks/audit-tip-signature.js +0 -336
  56. package/dist/infrastructure/hooks/claude-sdk-hook.js +0 -1018
  57. package/dist/infrastructure/hooks/hook-mode.js +0 -87
  58. package/dist/infrastructure/hooks/mirror-tool-call-to-audit.js +0 -49
  59. package/dist/infrastructure/hooks/pre-prompt-scan.js +0 -122
  60. package/dist/infrastructure/hooks/session-analyzer.js +0 -177
  61. package/dist/infrastructure/observability/execution-tracer.js +0 -227
  62. package/dist/infrastructure/orchestration/agent-adapter.js +0 -13
  63. package/dist/infrastructure/orchestration/agent-installer.js +0 -101
  64. package/dist/infrastructure/orchestration/agents-config-seed.js +0 -68
  65. package/dist/infrastructure/orchestration/aider-adapter.js +0 -611
  66. package/dist/infrastructure/orchestration/cassette-recorder.js +0 -120
  67. package/dist/infrastructure/orchestration/claude-code-adapter.js +0 -592
  68. package/dist/infrastructure/orchestration/codex-adapter.js +0 -574
  69. package/dist/infrastructure/orchestration/conductor-adapter.js +0 -416
  70. package/dist/infrastructure/orchestration/context-handoff.js +0 -162
  71. package/dist/infrastructure/orchestration/control/codex-control-surface.js +0 -99
  72. package/dist/infrastructure/orchestration/control/control-surface.js +0 -15
  73. package/dist/infrastructure/orchestration/detect-ollama.js +0 -75
  74. package/dist/infrastructure/orchestration/failover-classifier.js +0 -151
  75. package/dist/infrastructure/orchestration/failover-config.js +0 -67
  76. package/dist/infrastructure/orchestration/failover-policy.js +0 -106
  77. package/dist/infrastructure/orchestration/gemini-adapter.js +0 -663
  78. package/dist/infrastructure/orchestration/generic-cli-adapter.js +0 -689
  79. package/dist/infrastructure/orchestration/graphify-context.js +0 -209
  80. package/dist/infrastructure/orchestration/memory-injector.js +0 -380
  81. package/dist/infrastructure/orchestration/mocks/mock-agent-repl.js +0 -388
  82. package/dist/infrastructure/orchestration/mocks/mock-codex-app-server.js +0 -73
  83. package/dist/infrastructure/orchestration/mocks/mock-synthesis.js +0 -83
  84. package/dist/infrastructure/orchestration/mocks/resolve-agent-spawn.js +0 -37
  85. package/dist/infrastructure/orchestration/opencode-adapter.js +0 -580
  86. package/dist/infrastructure/orchestration/progress-aggregator.js +0 -906
  87. package/dist/infrastructure/orchestration/readiness.js +0 -103
  88. package/dist/infrastructure/orchestration/session-manager.js +0 -1590
  89. package/dist/infrastructure/orchestration/session-persistence.js +0 -394
  90. package/dist/infrastructure/orchestration/thread-key-store.js +0 -127
  91. package/dist/infrastructure/orchestration/write-pass-store.js +0 -38
  92. package/dist/infrastructure/protocols/cloud-sync.js +0 -207
  93. package/dist/infrastructure/protocols/mcp-helpers.js +0 -25
  94. package/dist/infrastructure/protocols/mcp-server-impl.js +0 -3935
  95. package/dist/infrastructure/protocols/mcp-tools.js +0 -401
  96. package/dist/infrastructure/protocols/probe-port.js +0 -36
  97. package/dist/infrastructure/protocols/thread-phase.js +0 -105
  98. package/dist/infrastructure/protocols/ui/app-script-artifacts.js +0 -121
  99. package/dist/infrastructure/protocols/ui/app-script-audit-footer.js +0 -44
  100. package/dist/infrastructure/protocols/ui/app-script-audit-verify.js +0 -56
  101. package/dist/infrastructure/protocols/ui/app-script-composer-cost.js +0 -588
  102. package/dist/infrastructure/protocols/ui/app-script-context-sources.js +0 -168
  103. package/dist/infrastructure/protocols/ui/app-script-conversation.js +0 -67
  104. package/dist/infrastructure/protocols/ui/app-script-drawer.js +0 -115
  105. package/dist/infrastructure/protocols/ui/app-script-failover.js +0 -133
  106. package/dist/infrastructure/protocols/ui/app-script-github.js +0 -113
  107. package/dist/infrastructure/protocols/ui/app-script-observer.js +0 -104
  108. package/dist/infrastructure/protocols/ui/app-script-onboarding.js +0 -80
  109. package/dist/infrastructure/protocols/ui/app-script-overlay.js +0 -203
  110. package/dist/infrastructure/protocols/ui/app-script-recovery.js +0 -136
  111. package/dist/infrastructure/protocols/ui/app-script-render.js +0 -166
  112. package/dist/infrastructure/protocols/ui/app-script-share.js +0 -78
  113. package/dist/infrastructure/protocols/ui/app-script-sidebar.js +0 -194
  114. package/dist/infrastructure/protocols/ui/app-script-tour.js +0 -78
  115. package/dist/infrastructure/protocols/ui/app-script-wpass.js +0 -312
  116. package/dist/infrastructure/protocols/ui/app-script.js +0 -2998
  117. package/dist/infrastructure/protocols/ui/font-faces.js +0 -7
  118. package/dist/infrastructure/protocols/ui/styles.js +0 -2147
  119. package/dist/infrastructure/protocols/ui/tokens.js +0 -96
  120. package/dist/infrastructure/protocols/ui-page-v2.js +0 -320
  121. package/dist/infrastructure/protocols/verify-page.js +0 -1677
  122. package/dist/infrastructure/security/file-collection.js +0 -118
  123. package/dist/infrastructure/security/fix-code.js +0 -144
  124. package/dist/infrastructure/security/fix-secret.js +0 -89
  125. package/dist/infrastructure/security/permissions-config.js +0 -235
  126. package/dist/infrastructure/security/scan-types.js +0 -10
  127. package/dist/infrastructure/security/ship-scan.js +0 -195
  128. package/dist/infrastructure/security/trust-scorer.js +0 -724
  129. package/dist/infrastructure/security/vibe-checks.js +0 -99
  130. package/dist/infrastructure/storage/atomic-write.js +0 -86
  131. package/dist/infrastructure/storage/cross-tool-agents.js +0 -268
  132. package/dist/infrastructure/storage/project-thread-migration.js +0 -237
  133. package/dist/infrastructure/storage/project-thread-mirror.js +0 -671
  134. package/dist/infrastructure/storage/project-thread-reader.js +0 -409
  135. package/dist/infrastructure/storage/project-thread-title-backfill.js +0 -214
  136. package/dist/monitoring.js +0 -212
  137. package/dist/presentation/cli/commands/audit-command.js +0 -201
  138. package/dist/presentation/cli/commands/budget-command.js +0 -79
  139. package/dist/presentation/cli/commands/config-command.js +0 -125
  140. package/dist/presentation/cli/commands/context-source-command.js +0 -217
  141. package/dist/presentation/cli/commands/hook-command.js +0 -265
  142. package/dist/presentation/cli/commands/init-command.js +0 -590
  143. package/dist/presentation/cli/commands/memory-command.js +0 -1031
  144. package/dist/presentation/cli/commands/narrator-command.js +0 -101
  145. package/dist/presentation/cli/commands/permission-command.js +0 -105
  146. package/dist/presentation/cli/commands/protocols-builder.js +0 -254
  147. package/dist/presentation/cli/commands/protocols-command.js +0 -84
  148. package/dist/presentation/cli/commands/repo-map-builder.js +0 -247
  149. package/dist/presentation/cli/commands/report-command.js +0 -403
  150. package/dist/presentation/cli/commands/scan-command.js +0 -52
  151. package/dist/presentation/cli/commands/scan-tool-command.js +0 -110
  152. package/dist/presentation/cli/commands/search-command.js +0 -51
  153. package/dist/presentation/cli/commands/setup-command.js +0 -330
  154. package/dist/presentation/cli/commands/status-command.js +0 -614
  155. package/dist/presentation/cli/commands/team-command.js +0 -256
  156. package/dist/presentation/cli/commands/thread-command.js +0 -370
  157. package/dist/presentation/cli/commands/trust-command.js +0 -328
  158. package/dist/presentation/cli/commands/verify-command.js +0 -298
  159. package/dist/presentation/cli/error-display.js +0 -328
  160. package/dist/presentation/cli/repl.js +0 -805
  161. package/dist/presentation/cli/task-deliverable.js +0 -153
  162. package/dist/testing/cassette.js +0 -125
  163. package/dist/testing/replay-adapter.js +0 -147
@@ -1,104 +0,0 @@
1
- /**
2
- * The observer rail — the calm one-line strip above TODAY showing terminal sessions codehere is
3
- * watching, expandable to the full rail, plus its duration formatting and toggle.
4
- *
5
- * Split out of app-script.ts (strangler fig, split 14). Verbatim slice, interpolated back where
6
- * it was cut so it keeps sharing the surrounding IIFE scope: fetchAll feeds it via
7
- * renderHostSessions, and the strip's own markup calls obsToggle through an inline handler.
8
- * Verified by hashing the composed APP_SCRIPT before and after: same bytes.
9
- *
10
- * Its empty state is deliberately conditional — the first-run teach only renders when there is
11
- * no real delegated activity, because "nothing to watch yet" sitting directly above a list of
12
- * the user's actual tasks is a visible contradiction.
13
- */
14
- export const OBSERVER_RAIL = `function renderHostSessions(data){
15
- // Thariq loop-2 (design B) -> S13: when sessions exist the observer is a
16
- // calm ONE-LINE row above TODAY ("● watching N terminal sessions · M live")
17
- // that expands to the full rail; first-run keeps the teach state.
18
- const strip=document.getElementById('observer-rail');
19
- if(!strip)return;
20
- _cached.host=data;
21
- // The observer belongs to the goals home, not inside a room.
22
- if(_room){ strip.style.display='none'; strip.innerHTML=''; return; }
23
- const sessions=(data&&data.sessions)||[];
24
- if(!sessions.length){
25
- // The empty-observer teach is FIRST-RUN orientation. Once the user has real
26
- // delegated activity, "nothing to watch yet" + the teach sits directly above
27
- // their actual task rows — a visible contradiction. Show the teach ONLY on a
28
- // genuine first run (no real tasks); otherwise the observer stays out of the
29
- // way (the hero already teaches the terminal-watch path).
30
- const _hasReal=allS(_cached.tasks||{}).some(t=>!/^demo-/.test(t.sessionId||'') && !t.mockRun);
31
- if(_hasReal){ strip.style.display='none'; strip.innerHTML=''; return; }
32
- // Rule 2 · empty observer TEACHES the 60-second path, never a blank box —
33
- // and never seeds fake rows (rule 3). data-verify-observer="empty" lets the
34
- // probe assert the teach-path renders.
35
- strip.innerHTML='<div class="observer-rail empty" data-verify-unit="observer" data-verify-observer="empty">'
36
- +'<div class="obs-head"><span class="obs-glyph idle">\\u25CB</span><span>nothing to watch yet</span></div>'
37
- +'<div class="obs-teach">Run <code>claude</code> (or codex / gemini / aider) in any terminal. The moment it makes a tool call, codehere records a verified, hash-chained log of what it did. Zero setup.</div>'
38
- +'</div>';
39
- strip.style.display='block';
40
- return;
41
- }
42
- function he(s){ return String(s).replace(/[&<>"]/g, c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[c])); }
43
- function obsDur(ms){ if(!ms||ms<1000)return'just now'; const s=Math.floor(ms/1000); if(s<60)return s+'s'; const m=Math.floor(s/60); if(m<60)return m+'m'; const h=Math.floor(m/60); return h+'h '+(m%60)+'m'; }
44
- function mix(tm){ return Object.entries(tm||{}).sort((a,b)=>b[1]-a[1]).slice(0,4).map(([k,v])=>he(k)+' '+v).join(' · '); }
45
- // live/recent/idle from last-event age · so a session that ended hours ago
46
- // stops claiming "observing" (honest · OPEN-HOST-SESSION-WEB-LIVE).
47
- function liveState(ls){ const age=Date.now()-new Date(ls).getTime(); if(!(age>=0))return'idle'; if(age<120000)return'live'; if(age<3600000)return'recent'; return'idle'; }
48
- function liveLabel(st){ return st==='live'?'live now':st==='recent'?'recent':'idle'; }
49
- // Explain the badge in plain English from the actual data · a bare "MEDIUM"
50
- // tells the user nothing about why. (per plain-English + no-screen-lies)
51
- function riskWhy(s){
52
- if(s.criticalCalls>0) return s.criticalCalls+' critical finding'+(s.criticalCalls===1?'':'s')+' · review';
53
- if(s.blockedCalls>0) return s.blockedCalls+' call'+(s.blockedCalls===1?'':'s')+' blocked before running · review';
54
- if(s.risk==='medium') return 'high-density session ('+s.totalCalls+' calls) · worth a glance if it ran unattended';
55
- return 'clean · '+s.totalCalls+' calls, nothing blocked';
56
- }
57
- const states=sessions.map(s=>liveState(s.lastSeen));
58
- const liveN=states.filter(s=>s==='live').length;
59
- const n=sessions.length;
60
- // S13 · at rest: one calm line. The per-session mini-dots carry the SAME
61
- // data-verify-obs-state contract as the expanded rows, so H8 keeps pinning
62
- // "claimed live === rendered live" in both states.
63
- if(!window._obsOpen){
64
- const minis=states.map((st,i)=>'<span class="obs-mini '+st+'" data-verify-obs-state="'+st+'" title="'+he(sessions[i].shortId)+' \\u00b7 '+liveLabel(st)+'"></span>').join('');
65
- strip.innerHTML='<div class="observer-rail collapsed" data-verify-unit="observer" data-verify-observer="active" data-verify-observer-live="'+liveN+'">'
66
- +'<div class="obs-line" role="button" tabindex="0" onclick="obsToggle()" onkeydown="if(event.key===\\'Enter\\')obsToggle()" title="expand \\u00b7 every observed session, hook-scanned + hash-chained">'
67
- +minis
68
- +'<span>following '+n+' terminal'+(n===1?'':'s')+(liveN>0?' \\u00b7 '+liveN+' live':' \\u00b7 none active right now')+'</span>'
69
- +'<span style="margin-left:auto">expand \\u203A</span>'
70
- +'</div></div>';
71
- strip.style.display='block';
72
- return;
73
- }
74
- let rows='';
75
- for(let i=0;i<sessions.length;i++){
76
- const s=sessions[i];
77
- const st=states[i];
78
- const blocked = s.blockedCalls>0 ? '<span class="obs-blocked" title="tool calls codehere blocked before they ran">'+s.blockedCalls+' blocked</span>' : '';
79
- // data-verify-obs-state lets the probe assert the live badge matches a
80
- // recent session — a stale session must never render "live".
81
- // S20 · Status lens: outcomes only — the per-tool mix is mechanics and
82
- // stays out of the row; blocked counts + risk are outcomes and stay.
83
- rows+='<div class="obs-row" data-verify-obs-state="'+st+'" onclick="showHostSession(\\''+he(s.shortId)+'\\')" title="open this session as a thread · see every tool call codehere observed">'
84
- +'<span class="obs-live '+st+'" title="'+liveLabel(st)+'"></span>'
85
- +'<span class="obs-id" title="'+he(s.sessionId)+'">'+he(s.shortId)+'</span>'
86
- +(curLens()==='status'?'':'<span class="obs-mix">'+mix(s.toolMix)+'</span>')
87
- +blocked
88
- +'<span class="obs-dur">'+obsDur(s.durationMs)+'</span>'
89
- +'<span class="obs-badge '+he(s.risk)+'" title="'+he(riskWhy(s))+'">'+he(s.risk)+'</span>'
90
- +'</div>';
91
- }
92
- const liveTxt = liveN>0 ? ' \\u00b7 <span class="obs-live-n">'+liveN+' live now</span>' : ' \\u00b7 none active right now';
93
- strip.innerHTML='<div class="observer-rail" data-verify-unit="observer" data-verify-observer="active" data-verify-observer-live="'+liveN+'">'
94
- +'<div class="obs-head"><span class="obs-glyph'+(liveN>0?' live':'')+'">\\u25CF</span><span>codehere is following <b>'+n+' coding-agent terminal'+(n===1?'':'s')+'</b>'+liveTxt+'</span><span class="obs-collapse" role="button" tabindex="0" onclick="obsToggle()" style="margin-left:auto;cursor:pointer;font-family:var(--mono);font-size:10.5px;color:var(--fg-40)">collapse</span></div>'
95
- +'<div class="obs-sub">You installed nothing extra \\u00b7 this is the agent already open in your shell. Every tool call is scanned by the hook, then hash-chained. Click one for a verified record of exactly what it did.</div>'
96
- +rows
97
- +'</div>';
98
- strip.style.display='block';
99
- }
100
- function obsToggle(){
101
- window._obsOpen=!window._obsOpen;
102
- renderHostSessions(_cached.host||{sessions:[]});
103
- }`;
104
- //# sourceMappingURL=app-script-observer.js.map
@@ -1,80 +0,0 @@
1
- /**
2
- * First-run onboarding — the non-blocking, dismissible welcome card on the home, its styles,
3
- * and the three actions it offers.
4
- *
5
- * Split out of app-script.ts (strangler fig, split 12). Verbatim slice, interpolated back where
6
- * it was cut so it keeps sharing the surrounding IIFE scope: render() calls
7
- * maybeStartOnboarding, the card's own markup calls welcomeRunTask/welcomeOpenSpend/
8
- * welcomeConnectTool through inline handlers, and dismissWelcome is reachable from the close
9
- * button. Verified by hashing the composed APP_SCRIPT before and after: same bytes.
10
- *
11
- * The card deliberately replaced a full-screen splash + forced tour — the workspace stays
12
- * usable underneath and the tour is replayable from the palette rather than ambushing anyone.
13
- */
14
- export const ONBOARDING = `// (Removed 2026-06-27: the dead full-screen welcome splash chain
15
- // startWelcome/welcomeSplash/welcomeSetup/finishWelcome — never called once the
16
- // non-blocking card below replaced it. The replayable tooltips tour
17
- // startTour/tourStep stays; obAgentsHtml stays — both still used by the teach card.)
18
- // First-run controller: a NON-BLOCKING, dismissible value-first welcome card on
19
- // the home (renderWelcomeCard) instead of the old full-screen splash + forced
20
- // tour. The workspace stays usable underneath. The tour is still replayable from
21
- // the command palette (Go -> Take the tour), just never forced.
22
- function maybeStartOnboarding(){
23
- if(_room||_detail) return; // home only, never ambush mid-work
24
- var onboarded=false;
25
- try{ onboarded=!!localStorage.getItem('ch_onboarded'); }catch(e){}
26
- if(onboarded) return;
27
- // Not a first run if there's already real work — a returning user with projects
28
- // or sessions shouldn't get a "Run your first task" card owning the top of the
29
- // home. Only a genuine first run (no projects, no real tasks) sees it.
30
- var hasWork=((_cached.projects||[]).length>0) || allS(_cached.tasks||{}).some(function(t){return !/^demo-/.test(t.sessionId||'');});
31
- if(hasWork){ try{ localStorage.setItem('ch_onboarded','1'); }catch(e){} return; }
32
- renderWelcomeCard();
33
- }
34
- var _HW_CSS=[
35
- '#home-welcome{margin:0 0 18px}',
36
- '#home-welcome .hw-card{position:relative;background:linear-gradient(135deg,rgba(255,154,118,.06),rgba(74,144,226,.05));border:1px solid var(--border,rgba(255,255,255,.1));border-radius:12px;padding:20px 22px;max-width:760px}',
37
- '#home-welcome .hw-x{position:absolute;top:12px;right:15px;color:var(--fg-40,rgba(255,255,255,.4));font-size:14.5px;cursor:pointer;line-height:1}',
38
- '#home-welcome .hw-h2{font-size:14.5px;font-weight:700;color:var(--fg)}',
39
- '#home-welcome .hw-lede{font-size:13px;color:var(--fg-70,rgba(255,255,255,.72));margin:6px 0 16px;line-height:1.5;max-width:560px}',
40
- '#home-welcome .hw-steps{display:flex;gap:10px;margin-bottom:16px;flex-wrap:wrap}',
41
- '#home-welcome .hw-step{flex:1;min-width:168px;background:var(--bg-1,hsl(0 0% 6%));border:1px solid var(--border,rgba(255,255,255,.1));border-radius:9px;padding:11px 12px}',
42
- '#home-welcome .hw-n{font-size:10.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--accent)}',
43
- '#home-welcome .hw-t{font-size:12px;font-weight:600;color:var(--fg);margin:3px 0 2px}',
44
- '#home-welcome .hw-d{font-size:12px;color:var(--fg-50,rgba(255,255,255,.5));line-height:1.4}',
45
- '#home-welcome .hw-cta{display:flex;align-items:center;gap:10px;flex-wrap:wrap}',
46
- '#home-welcome .hw-btn{font-size:12px;font-weight:600;border-radius:8px;padding:8px 14px;cursor:pointer;border:1px solid var(--border,rgba(255,255,255,.1));font-family:inherit}',
47
- '#home-welcome .hw-primary{background:var(--accent);color:#0a0a0a;border-color:var(--accent)}',
48
- '#home-welcome .hw-ghost{background:none;color:var(--fg-70,rgba(255,255,255,.72))}',
49
- '#home-welcome .hw-ptr{margin-left:auto;font-size:12px;color:var(--fg-50,rgba(255,255,255,.5))}',
50
- '#home-welcome .hw-ptr b{color:var(--fg-70,rgba(255,255,255,.72))}',
51
- '#home-welcome .hw-note{font-size:12px;color:var(--fg-70,rgba(255,255,255,.72));margin-top:12px;padding-top:10px;border-top:1px solid var(--border-soft,rgba(255,255,255,.06))}'
52
- ].join('');
53
- function renderWelcomeCard(){
54
- var el=document.getElementById('home-welcome'); if(!el) return;
55
- if(el.getAttribute('data-rendered')==='1') return; // idempotent across re-renders
56
- el.setAttribute('data-rendered','1');
57
- el.innerHTML='<style id="hw-css">'+_HW_CSS+'</style>'
58
- +'<div class="hw-card">'
59
- +'<span class="hw-x" onclick="dismissWelcome()" title="Dismiss">\\u2715</span>'
60
- +'<h2 class="hw-h2">Welcome to codehere</h2>'
61
- +'<div class="hw-lede">Run your coding agents in one place, on a bill that won\\u2019t surprise you, with a record of what each did. All on your machine, no account.</div>'
62
- +'<div class="hw-steps">'
63
- +'<div class="hw-step"><div class="hw-n">1</div><div class="hw-t">Run a task</div><div class="hw-d">Type a goal below, pick an agent, watch it work.</div></div>'
64
- +'<div class="hw-step"><div class="hw-n">2</div><div class="hw-t">Connect a tool</div><div class="hw-d">Turn Linear or GitHub issues into tasks.</div></div>'
65
- +'<div class="hw-step"><div class="hw-n">3</div><div class="hw-t">See the bill + record</div><div class="hw-d">Spend and the audit live under Spend &amp; Audit.</div></div>'
66
- +'</div>'
67
- +'<div class="hw-cta"><button class="hw-btn hw-primary" onclick="welcomeRunTask()">Run your first task</button>'
68
- +'<button class="hw-btn hw-ghost" onclick="welcomeConnectTool()">Connect a tool</button>'
69
- +'<span class="hw-ptr">cost &amp; record: <b onclick="welcomeOpenSpend()" style="cursor:pointer">Spend &amp; Audit \\u203A</b></span></div>'
70
- +'<div class="hw-note" id="hw-note" style="display:none"></div>'
71
- +'</div>';
72
- el.style.display='block';
73
- }
74
- function dismissWelcome(){
75
- try{ localStorage.setItem('ch_onboarded','1'); }catch(e){}
76
- var el=document.getElementById('home-welcome'); if(el){ el.innerHTML=''; el.style.display='none'; el.removeAttribute('data-rendered'); }
77
- }
78
- function welcomeRunTask(){ dismissWelcome(); var ta=document.getElementById('main-ta'); if(ta){ try{ ta.scrollIntoView({behavior:'smooth',block:'center'}); }catch(e){} ta.focus(); } }
79
- function welcomeOpenSpend(){ if(typeof showSpend==='function') showSpend(); }`;
80
- //# sourceMappingURL=app-script-onboarding.js.map
@@ -1,203 +0,0 @@
1
- /**
2
- * Overlay renderer — the inspect-and-act panel behind every .ctx-url-chip: fetch what a URL
3
- * actually resolves to, render it per source, and let the user act on it.
4
- *
5
- * Split out of app-script.ts (strangler fig, split 6). Verbatim slice, interpolated back at
6
- * the position it was cut from so it keeps sharing the surrounding IIFE scope — the Escape
7
- * handler left behind still calls orClose. Verified by hashing the composed APP_SCRIPT
8
- * before and after: same bytes.
9
- */
10
- export const OVERLAY_RENDERER = ` /* v0.9 S7 · overlay-renderer · inspect-and-act */
11
- const orOverlay = document.getElementById('or-overlay');
12
- const orBody = document.getElementById('or-body');
13
- function orClose(){ orOverlay.classList.remove('open'); }
14
- function orSchemeOf(url){ const m = String(url||'').match(/^([a-z][a-z0-9+.-]*):/); return m ? m[1] : '?'; }
15
- function orEscape(s){
16
- return String(s||'').replace(/[&<>"]/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[c]));
17
- }
18
- function orRenderLoading(scheme, url){
19
- document.getElementById('or-src').textContent = scheme;
20
- document.getElementById('or-meta').textContent = '· fetching ' + url;
21
- document.getElementById('or-hint').textContent = orComposerHintFor(scheme);
22
- document.getElementById('or-input').placeholder = orPlaceholderFor(scheme);
23
- orBody.innerHTML = '<div class="preview-loading">fetching from ' + orEscape(scheme) + '…</div>';
24
- }
25
- function orComposerHintFor(scheme){
26
- if(scheme==='linear') return 'Ask the agent about this Linear ticket · all interaction captured in audit chain';
27
- if(scheme==='github') return 'Ask the agent about this GitHub issue or PR · all interaction captured';
28
- if(scheme==='figma') return 'Ask the agent about this Figma frame · all interaction captured';
29
- if(scheme==='drawio') return 'Ask the agent about this diagram · all interaction captured';
30
- return 'Ask the agent about this · all interaction captured';
31
- }
32
- function orPlaceholderFor(scheme){
33
- if(scheme==='linear') return "e.g. summarize the blocker · or what's the priority?";
34
- if(scheme==='github') return "e.g. what's the discussion about · what changed last comment?";
35
- if(scheme==='figma') return "e.g. extract the design tokens · what fields are in the modal?";
36
- if(scheme==='drawio') return "e.g. what's the request flow · where does the queue sit?";
37
- return 'Ask about this resource…';
38
- }
39
- function orRenderError(scheme, url, kind, message){
40
- let hint = '';
41
- if(kind==='auth') hint = 'Open Settings \\u203A Integrations to connect '+scheme+'.';
42
- else if(kind==='not_found') hint = 'The resource at '+url+' was not reachable.';
43
- else if(kind==='rate_limit') hint = 'The '+scheme+' API is rate-limited · try again in a minute.';
44
- else if(kind==='invalid_url') hint = 'codehere has no adapter for that URL scheme.';
45
- orBody.innerHTML =
46
- '<div class="preview-error">' +
47
- '<div>' + orEscape(message) + '</div>' +
48
- (hint ? '<div class="hint">' + orEscape(hint) + '</div>' : '') +
49
- '</div>';
50
- }
51
- function orRenderPayload(payload){
52
- const meta = payload.metadata || {};
53
- document.getElementById('or-meta').textContent =
54
- '· ' + (meta.bytes ? meta.bytes + ' bytes' : (payload.estimatedTokens ? '~' + payload.estimatedTokens + ' tokens' : '')) +
55
- ' · fetched ' + (payload.fetchedAt || '').slice(11,19);
56
- // Per-source structured render · Linear gets the demo v12 authentic
57
- // ticket card · everything else falls back to title + meta-pills + plain text.
58
- if(payload.source === 'linear'){
59
- orBody.innerHTML = orRenderLinear(payload);
60
- return;
61
- }
62
- if(payload.source === 'figma'){
63
- orBody.innerHTML = orRenderFigma(payload);
64
- return;
65
- }
66
- if(payload.source === 'drawio'){
67
- orBody.innerHTML = orRenderDrawio(payload);
68
- return;
69
- }
70
- const titleCandidate =
71
- meta.title || meta.label ||
72
- (meta.identifier ? meta.identifier + ' · ' + (meta.title||'') : null) ||
73
- payload.url;
74
- let pillsHtml = '';
75
- if(meta.state){
76
- const cls = meta.state === 'open' ? 'state-open' : meta.state === 'closed' ? 'state-closed' : '';
77
- pillsHtml += '<span class="pill ' + cls + '">' + orEscape(meta.state) + '</span>';
78
- }
79
- if(meta.author) pillsHtml += '<span class="pill">@' + orEscape(meta.author) + '</span>';
80
- if(meta.assignee) pillsHtml += '<span class="pill">\\u203A ' + orEscape(meta.assignee) + '</span>';
81
- if(meta.priorityLabel) pillsHtml += '<span class="pill">' + orEscape(meta.priorityLabel) + '</span>';
82
- if(typeof meta.commentCount === 'number') pillsHtml += '<span class="pill">' + meta.commentCount + ' comments</span>';
83
- if(typeof meta.cellCount === 'number') pillsHtml += '<span class="pill">' + meta.cellCount + ' cells</span>';
84
- if(typeof meta.edgeCount === 'number') pillsHtml += '<span class="pill">' + meta.edgeCount + ' edges</span>';
85
- orBody.innerHTML =
86
- '<h3>' + orEscape(titleCandidate) + '</h3>' +
87
- '<div class="url-row">' + orEscape(payload.url) + '</div>' +
88
- (pillsHtml ? '<div class="meta-row">' + pillsHtml + '</div>' : '') +
89
- '<div class="preview-text">' + orEscape(payload.text) + '</div>';
90
- }
91
- function orRenderLinear(payload){
92
- const m = payload.metadata || {};
93
- const initials = (m.assignee||'').split(/\\s+/).map(w=>w[0]||'').join('').slice(0,2).toUpperCase() || '??';
94
- const priCls = (m.priorityLabel||'').toLowerCase().includes('urgent') ? 'linear-pri-urgent' : '';
95
- const stateCls = String(m.stateType||m.state||'').toLowerCase().includes('progress') ? 'linear-status-progress' : '';
96
- const props = [];
97
- if(m.priorityLabel) {
98
- props.push('<span class="linear-pill '+priCls+'"><span class="lin-icn linear-pri-bars"><div></div><div></div><div></div></span>'+orEscape(m.priorityLabel)+'</span>');
99
- }
100
- if(m.state) {
101
- props.push('<span class="linear-pill '+stateCls+'"><span class="lin-icn linear-status-circle"></span>'+orEscape(m.state)+'</span>');
102
- }
103
- if(m.assignee) {
104
- props.push('<span class="linear-pill linear-assignee"><span class="av" style="background:#76b7ff">'+orEscape(initials)+'</span>'+orEscape(m.assignee)+'</span>');
105
- }
106
- const commentsHtml = (m.comments||[]).map(c=>{
107
- const ini = (c.author||'').split(/\\s+/).map(w=>w[0]||'').join('').slice(0,2).toUpperCase() || '??';
108
- return '<div class="linear-comment">'+
109
- '<div class="av">'+orEscape(ini)+'</div>'+
110
- '<div class="col">'+
111
- '<div class="who">'+orEscape(c.author)+' <span class="ts">'+orEscape((c.createdAt||'').slice(0,10))+'</span></div>'+
112
- '<div class="body">'+orEscape(c.body||'')+'</div>'+
113
- '</div></div>';
114
- }).join('');
115
- return '<div class="linear-render">'+
116
- '<div class="linear-id">'+orEscape(m.identifier||payload.url)+'</div>'+
117
- '<div class="linear-title">'+orEscape(m.title||'(no title)')+'</div>'+
118
- (props.length ? '<div class="linear-props">'+props.join('')+'</div>' : '')+
119
- (m.description ? '<div class="linear-desc">'+orEscape(m.description.slice(0,800))+'</div>' : '')+
120
- (commentsHtml ? '<div class="linear-sep"><span class="lbl">Activity</span><div class="line"></div></div>'+commentsHtml : '')+
121
- '</div>';
122
- }
123
- function orRenderFigma(payload){
124
- // Figma is text-only by design · agents read structure, not pixels. The
125
- // card surfaces the frame tree (name · dims · first text), never a thumbnail.
126
- const m = payload.metadata || {};
127
- const frames = Array.isArray(m.frames) ? m.frames : [];
128
- const framesHtml = frames.map(function(f){
129
- const dim = (typeof f.width === 'number' && typeof f.height === 'number') ? (f.width + '×' + f.height) : '';
130
- return '<div class="figma-frame">'+
131
- '<span class="figma-frame-name">'+orEscape(f.name||'(frame)')+'</span>'+
132
- (dim ? '<span class="figma-frame-dim">'+orEscape(dim)+'</span>' : '')+
133
- (f.text ? '<div class="figma-frame-text">'+orEscape(f.text)+'</div>' : '')+
134
- '</div>';
135
- }).join('');
136
- return '<div class="overlay-figma figma-render">'+
137
- '<div class="figma-head"><span class="figma-badge">Figma</span>'+
138
- '<span class="figma-name">'+orEscape(m.name||m.fileKey||payload.url)+'</span></div>'+
139
- '<div class="url-row">'+orEscape(payload.url)+'</div>'+
140
- (m.lastModified ? '<div class="figma-meta">updated '+orEscape(String(m.lastModified).slice(0,10))+'</div>' : '')+
141
- (frames.length
142
- ? '<div class="figma-sep"><span class="lbl">Frames ('+frames.length+')</span><div class="line"></div></div>'+framesHtml
143
- : '<div class="figma-note">text-only · no top-level frames in this node</div>')+
144
- '<div class="figma-sep"><span class="lbl">Tree</span><div class="line"></div></div>'+
145
- '<pre class="figma-tree">'+orEscape(payload.text)+'</pre>'+
146
- '</div>';
147
- }
148
- function orRenderDrawio(payload){
149
- // draw.io ships structure + raw XML, never a rendered diagram image. The
150
- // card shows the cell/edge/page stats + an XML excerpt · no pixel render.
151
- const m = payload.metadata || {};
152
- const stat = function(n,label){ return '<div class="drawio-stat"><span class="n">'+(typeof n==='number'?n:'-')+'</span><span class="l">'+label+'</span></div>'; };
153
- return '<div class="overlay-drawio drawio-render">'+
154
- '<div class="drawio-head"><span class="drawio-badge">draw.io</span>'+
155
- '<span class="drawio-name">'+orEscape(m.label||payload.url)+'</span></div>'+
156
- '<div class="url-row">'+orEscape(payload.url)+'</div>'+
157
- '<div class="drawio-stats">'+
158
- stat(m.cellCount,'cells')+stat(m.edgeCount,'edges')+stat(m.pageCount,'pages')+
159
- (typeof m.bytes==='number'?stat(m.bytes,'bytes'):'')+
160
- '</div>'+
161
- '<div class="drawio-sep"><span class="lbl">XML</span><div class="line"></div></div>'+
162
- '<pre class="drawio-xml">'+orEscape(payload.text)+'</pre>'+
163
- '</div>';
164
- }
165
- async function openOverlayFor(url){
166
- const scheme = orSchemeOf(url);
167
- orRenderLoading(scheme, url);
168
- orOverlay.classList.add('open');
169
- document.getElementById('or-input').value = '';
170
- try{
171
- const r = await fetch('/api/context-source/preview?url=' + encodeURIComponent(url));
172
- const j = await r.json();
173
- if(!r.ok || !j.ok){
174
- orRenderError(scheme, url, (j && j.kind) || 'unknown', (j && j.error) || ('HTTP ' + r.status));
175
- return;
176
- }
177
- orRenderPayload(j.payload);
178
- }catch(err){
179
- orRenderError(scheme, url, 'network', (err && err.message) || String(err));
180
- }
181
- }
182
- // Click delegation · any element with .ctx-url-chip + data-url opens the overlay.
183
- document.addEventListener('click', (e)=>{
184
- const el = (e.target instanceof Element) ? e.target.closest('.ctx-url-chip') : null;
185
- if(!el) return;
186
- const url = el.getAttribute('data-url') || el.textContent.trim();
187
- if(url) openOverlayFor(url);
188
- });
189
- document.getElementById('or-close')?.addEventListener('click', orClose);
190
- orOverlay?.addEventListener('click', e=>{ if(e.target === orOverlay) orClose(); });
191
- // Make openOverlayFor reachable by other scripts that want to attach explicit
192
- // open buttons (e.g. settings drawer · history rows · adapter examples).
193
- window.codehereOpenOverlay = openOverlayFor;
194
- // Render a fetched payload into the overlay without a live fetch · used by the
195
- // verify-page harness to drive the per-source render branches over a fixture
196
- // payload (the same shape the adapter unit fixtures produce).
197
- window.codehereRenderOverlayPayload = function(payload){
198
- const src = document.getElementById('or-src');
199
- if(src) src.textContent = (payload && payload.source) || '?';
200
- orOverlay.classList.add('open');
201
- orRenderPayload(payload);
202
- };`;
203
- //# sourceMappingURL=app-script-overlay.js.map
@@ -1,136 +0,0 @@
1
- /**
2
- * Recovery actions — stop a running agent, retry, diagnose, resolve, and override a blocked
3
- * tool call. The buttons on the highest-stakes screen, where a control that narrates an action
4
- * it did not perform is the worst lie the dashboard can tell.
5
- *
6
- * Split out of app-script.ts (strangler fig). Verbatim slice, interpolated back at the
7
- * position it was cut from so it keeps sharing the surrounding IIFE scope. Verified by
8
- * hashing the composed APP_SCRIPT before and after: same bytes.
9
- */
10
- export const RECOVERY_ACTIONS = `// Thariq loop-1 · the three REAL recovery handlers. Each does what its button
11
- // says or nothing renders the button as enabled (the recovery-buttons-must-
12
- // not-lie probe enforces it). Replaces the al() toasts that narrated actions
13
- // that never happened — a §3 honesty violation on the highest-stakes screen.
14
- /* S2 · stop a running agent. Success refreshes from the server (the status
15
- change is the proof); failure leaves a PERSISTENT plain reason where the
16
- button was — never a vanishing toast, never a silent flash of success. */
17
- async function stopTask(ev, sessionId){
18
- if(ev){ ev.stopPropagation(); if(ev.preventDefault) ev.preventDefault(); }
19
- const btn=ev && (ev.currentTarget||ev.target);
20
- // local escape — the he() helpers are nested in other render scopes and
21
- // unreachable here; the acceptance walk caught the failure branch itself
22
- // crashing on it ('he is not defined' -> button stuck on 'stopping…').
23
- const esc=function(x){ return String(x).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;'); };
24
- if(btn){ btn.disabled=true; btn.textContent='stopping\\u2026'; }
25
- try{
26
- const r=await fetch('/api/task/'+encodeURIComponent(sessionId)+'/kill',{method:'POST'});
27
- if(!r.ok){
28
- const e=await r.json().catch(function(){return {};});
29
- // S13 · the palette calls stopTask with no button — the failure must
30
- // still land on screen (toast), never a silent no-op.
31
- if(btn) btn.outerHTML='<span class="stop-fail">couldn\\u2019t stop \\u00B7 '+esc(String(e.error||('HTTP '+r.status)))+'</span>';
32
- else al('Couldn\\u2019t stop \\u00b7 '+String(e.error||('HTTP '+r.status)));
33
- return;
34
- }
35
- if(btn) btn.textContent='stopped'; else al('\\u25A0 stopped \\u00b7 the run ends as stopped');
36
- fetchAll();
37
- }catch(e){
38
- if(btn) btn.outerHTML='<span class="stop-fail">couldn\\u2019t stop \\u00B7 '+esc(String((e&&e.message)||e))+'</span>';
39
- else al('Couldn\\u2019t stop \\u00b7 '+String((e&&e.message)||e));
40
- }
41
- }
42
- async function recoverRetry(sessionId){
43
- const t=findS(sessionId); if(!t||!t.prompt){al('Cannot retry · the original prompt was not recorded');return;}
44
- const payload={prompt:t.prompt};
45
- if(t.cwd) payload.cwd=t.cwd;
46
- if(t.agent && t.agent!=='conductor') payload.agent=t.agent;
47
- try{
48
- const r=await fetch('/api/task',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(payload)});
49
- if(r.ok){ hideD(); fetchAll(); al('Retrying \\u00b7 a fresh agent is respawning on the same prompt'); }
50
- else { const e=await r.json().catch(()=>({})); al('Retry failed: '+(e.error||'unknown')); }
51
- }catch(e){ al('Retry failed \\u00b7 network error: '+e.message); }
52
- }
53
- // S14 · retry a CAUGHT task with the verifier's finding attached. Honest
54
- // construction only: the respawn prompt is the task's own recorded prompt
55
- // plus the real finding (claim + reality verbatim) or, when no structured
56
- // finding exists, the verdict summary. The button that calls this renders
57
- // only when t.prompt exists — otherwise it is disabled-with-reason (H7).
58
- async function recoverRetryAttach(sessionId){
59
- const t=findS(sessionId); if(!t||!t.prompt){al('Cannot retry \\u00b7 the original prompt was not recorded');return;}
60
- const _vr=t.verdict&&t.verdict.claim;
61
- const _f=(_vr&&_vr.findings&&_vr.findings[0])||null;
62
- let prompt=String(t.prompt);
63
- if(_f&&(_f.claim||_f.reality)){
64
- prompt+='\\n\\n[verifier finding from the previous run] claim: '+String(_f.claim||'(none recorded)')+' \\u00b7 reality: '+String(_f.reality||'(none recorded)')+' \\u00b7 close this gap and make the claim true before reporting done.';
65
- } else if(_vr&&_vr.summary){
66
- prompt+='\\n\\n[verifier verdict from the previous run] '+String(_vr.summary)+' \\u00b7 close this gap and make the claim true before reporting done.';
67
- }
68
- const payload={prompt:prompt};
69
- if(t.cwd) payload.cwd=t.cwd;
70
- if(t.agent && t.agent!=='conductor') payload.agent=t.agent;
71
- try{
72
- const r=await fetch('/api/task',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(payload)});
73
- if(r.ok){ hideD(); fetchAll(); al('Retrying with the contradiction attached \\u00b7 a fresh agent is respawning'); }
74
- else { const e=await r.json().catch(()=>({})); al('Retry failed: '+(e.error||'unknown')); }
75
- }catch(e){ al('Retry failed \\u00b7 network error: '+e.message); }
76
- }
77
- function recoverDiagnose(sessionId){
78
- // Focus the captured failing step in this detail's timeline — a real move,
79
- // not a new view. EVERY per-step card branch (tool-card + write-pass) emits
80
- // data-step-failed on a failed step, so an enabled Diagnose always has a
81
- // target; the recovery card itself is the guaranteed fallback. The button
82
- // NEVER toasts (the refuter caught a write-pass-step path where it did) —
83
- // it always scrolls+highlights a real element. (v2: a standalone diagnose.)
84
- const el=document.querySelector('[data-step-failed="1"]') || document.querySelector('.recovery-card');
85
- if(el){ el.scrollIntoView({behavior:'smooth',block:'center'}); el.style.outline='2px solid var(--accent)'; el.style.outlineOffset='2px'; setTimeout(()=>{el.style.outline='';},2400); }
86
- }
87
- async function recoverResolve(sessionId, btn){
88
- // A human acknowledgement belongs in the audit chain — write it there
89
- // (reusing the override-audit endpoint, the existing human-ack-into-chain
90
- // path). On success, badge the card; on failure, say so honestly.
91
- try{
92
- const r=await fetch('/api/audit/override',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({sessionId,toolName:'recovery',reasonType:'recovery_ack',reason:'recovery: marked resolved by the human'})}).then(x=>x.json()).catch(()=>null);
93
- const card=btn&&btn.closest('.recovery-card');
94
- if(r&&!r.error&&card){
95
- const ack=document.createElement('div'); ack.className='recovery-ack';
96
- ack.textContent='\\u2713 acknowledged by you \\u00b7 recorded in the audit chain'+(r.seq!=null?' \\u00b7 #'+r.seq:'');
97
- card.appendChild(ack); btn.disabled=true;
98
- card.setAttribute('data-verify-recovery','resolved');
99
- fetchAll(); // S3 · pull the persisted resolvedAt so the badge is state-backed from now on
100
- } else { al('Could not record the acknowledgement'+(r&&r.error?': '+r.error:'')); }
101
- }catch(e){ al('Could not record the acknowledgement \\u00b7 network error'); }
102
- }
103
-
104
- // E-03 · user override · reveal a reason input, then POST a real audit entry.
105
- // Replaces the old al('Override flow goes to v0.8') lie with a real hash-chain
106
- // append. The returned shortHash is the REAL chain tip, not a mockup.
107
- function overrideBlock(sessionId, toolName){
108
- const actions=document.getElementById('hook-block-actions');
109
- if(!actions||actions.dataset.open==='1')return;
110
- actions.dataset.open='1';
111
- actions.innerHTML='<input id="override-reason" placeholder="Why are you overriding this block?" style="flex:1;background:var(--bg-2,#1a1a1f);border:1px solid var(--border);border-radius:5px;color:var(--fg);padding:6px 8px;font-size:12px"/>'
112
- +'<button id="override-submit">Log + proceed</button>'
113
- +'<button id="override-cancel">Cancel</button>';
114
- const inp=document.getElementById('override-reason'); if(inp)inp.focus();
115
- document.getElementById('override-cancel').onclick=()=>{ if(_detail)showD(_detail); };
116
- document.getElementById('override-submit').onclick=async()=>{
117
- const reason=(document.getElementById('override-reason')||{}).value||'';
118
- if(!reason.trim()){ al('A reason is required to log an override'); return; }
119
- try{
120
- const r=await fetch('/api/audit/override',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({sessionId,toolName,reason})}).then(x=>x.json());
121
- const res=document.getElementById('override-result');
122
- if(r&&r.ok){
123
- actions.innerHTML='';
124
- if(res)res.innerHTML='<span class="ok">\\u2713</span> override logged · chain continues <code>'+(r.shortHash||('#'+r.seq))+'</code>';
125
- } else { al('Override failed: '+((r&&r.error)||'unknown')); }
126
- }catch(e){ al('Network error: '+e.message); }
127
- };
128
- }
129
-
130
- async function a(action, id) {
131
- // Only 'kill' is a real, wired action today. Pause/resume/restart were
132
- // unwired stubs with no callers — removed (production-grade · no dead
133
- // "not yet wired" affordances). Re-add when real agent-process control lands.
134
- if(action==='kill'){ try{await fetch('/api/task/'+id+'/kill',{method:'POST'});fetchAll();}catch(e){al('Failed: '+e.message);} return; }
135
- }`;
136
- //# sourceMappingURL=app-script-recovery.js.map