@worca/app 1.0.0 → 1.1.1

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 (138) hide show
  1. package/README.md +22 -9
  2. package/agents/clarify.meta.json +4 -4
  3. package/agents/decomposer.meta.json +5 -5
  4. package/agents/implementer.meta.json +15 -5
  5. package/agents/manualTestsChecklist.meta.json +5 -4
  6. package/agents/manualWebUiTesting.meta.json +9 -4
  7. package/agents/planReviewer.meta.json +12 -4
  8. package/agents/planner.meta.json +12 -5
  9. package/agents/refiner.meta.json +15 -4
  10. package/agents/reviewer.meta.json +14 -4
  11. package/agents/worca-cc-clarify.md +7 -0
  12. package/agents/worca-cc-code-reviewer.md +11 -6
  13. package/agents/worca-cc-decomposer.md +7 -0
  14. package/agents/worca-cc-implementer.md +9 -0
  15. package/agents/worca-cc-manual-tests-checklist.md +8 -5
  16. package/agents/worca-cc-manual-web-ui-testing.md +10 -6
  17. package/agents/worca-cc-plan-refiner.md +11 -6
  18. package/agents/worca-cc-plan-reviewer.md +10 -7
  19. package/agents/worca-cc-planner.md +9 -0
  20. package/agents/worca-cc-workspace-reviewer.md +11 -4
  21. package/agents/worca-cc-workspace-scanner.md +8 -4
  22. package/agents/workspaceReviewer.meta.json +15 -4
  23. package/agents/workspaceScanner.meta.json +5 -4
  24. package/package.json +8 -2
  25. package/skills/worca/SKILL.md +5 -5
  26. package/src/cli/render.mjs +148 -0
  27. package/src/cli/worca-cc.mjs +319 -45
  28. package/src/core/agent-gen.mjs +69 -31
  29. package/src/core/agent-registry.mjs +124 -144
  30. package/src/core/agent-store.mjs +164 -4
  31. package/src/core/artifacts.mjs +189 -21
  32. package/src/core/ask/catalog.mjs +111 -0
  33. package/src/core/ask/comment-deps.mjs +55 -0
  34. package/src/core/ask/events.mjs +506 -0
  35. package/src/core/ask/follow.mjs +107 -0
  36. package/src/core/ask/git-allowlist.mjs +226 -0
  37. package/src/core/ask/limits.mjs +54 -0
  38. package/src/core/ask/mcp-stdio.mjs +135 -0
  39. package/src/core/ask/models.mjs +125 -0
  40. package/src/core/ask/prompt.mjs +261 -0
  41. package/src/core/ask/proposal.mjs +170 -0
  42. package/src/core/ask/redact.mjs +30 -0
  43. package/src/core/ask/spawn.mjs +153 -0
  44. package/src/core/ask/store.mjs +360 -0
  45. package/src/core/ask/tool-deps.mjs +63 -0
  46. package/src/core/ask/tools.mjs +848 -0
  47. package/src/core/ask/turn.mjs +416 -0
  48. package/src/core/ask/worktree-deps.mjs +27 -0
  49. package/src/core/ask/worktrees.mjs +285 -0
  50. package/src/core/chat/command-router.mjs +20 -3
  51. package/src/core/claude-runner.mjs +434 -57
  52. package/src/core/config.mjs +264 -41
  53. package/src/core/cost-budget.mjs +29 -2
  54. package/src/core/db.mjs +684 -47
  55. package/src/core/diff-anchor.mjs +213 -0
  56. package/src/core/diff-comments.mjs +273 -0
  57. package/src/core/engine-select.mjs +32 -0
  58. package/src/core/git-info.mjs +49 -10
  59. package/src/core/graph/builtin-workflows.mjs +51 -0
  60. package/src/core/graph/executor.mjs +894 -0
  61. package/src/core/graph/registry-ports.mjs +12 -0
  62. package/src/core/graph/scheduler.mjs +1065 -0
  63. package/src/core/graph/seed-templates.mjs +318 -0
  64. package/src/core/model-env.mjs +112 -8
  65. package/src/core/model-test.mjs +79 -0
  66. package/src/core/orchestrator.mjs +902 -4098
  67. package/src/core/overview-agent.mjs +15 -3
  68. package/src/core/phases.mjs +208 -537
  69. package/src/core/pipeline-delete.mjs +13 -2
  70. package/src/core/plugin-api.mjs +8 -3
  71. package/src/core/plugin-config.mjs +178 -28
  72. package/src/core/plugin-inventory.mjs +6 -2
  73. package/src/core/plugin-manifest.mjs +199 -11
  74. package/src/core/plugin-models.mjs +1 -0
  75. package/src/core/plugin-repo.mjs +16 -4
  76. package/src/core/plugin-shim-child.mjs +9 -3
  77. package/src/core/plugin-shim.mjs +77 -14
  78. package/src/core/plugin-store.mjs +236 -29
  79. package/src/core/plugin-workflows.mjs +90 -41
  80. package/src/core/preflight.mjs +135 -3
  81. package/src/core/projects.mjs +7 -5
  82. package/src/core/protocol.mjs +8 -35
  83. package/src/core/recoverable-error.mjs +1 -1
  84. package/src/core/run-harness.mjs +3585 -0
  85. package/src/core/run-manifest.mjs +5 -1
  86. package/src/core/settings.mjs +109 -13
  87. package/src/core/skills.mjs +10 -3
  88. package/src/core/source-bindings.mjs +175 -0
  89. package/src/core/sources.mjs +87 -25
  90. package/src/core/stats.mjs +25 -6
  91. package/src/core/title.mjs +51 -4
  92. package/src/core/workflows.mjs +358 -259
  93. package/src/core/workspace-scan.mjs +4 -0
  94. package/src/core/worktree.mjs +98 -7
  95. package/src/shared/graph/agent-meta.mjs +278 -0
  96. package/src/shared/graph/constants.mjs +105 -0
  97. package/src/shared/graph/geometry.mjs +157 -0
  98. package/src/shared/graph/layout.mjs +134 -0
  99. package/src/shared/graph/loops.mjs +130 -0
  100. package/src/shared/graph/manifest.mjs +257 -0
  101. package/src/shared/graph/ports.mjs +153 -0
  102. package/src/shared/graph/route.mjs +397 -0
  103. package/src/shared/graph/template.mjs +165 -0
  104. package/src/shared/graph/thumbnail.mjs +67 -0
  105. package/src/shared/graph/validate.mjs +491 -0
  106. package/src/shared/graph/verdict.mjs +41 -0
  107. package/ui/public/app.js +4008 -1670
  108. package/ui/public/ask-markdown.mjs +145 -0
  109. package/ui/public/ask-model.mjs +264 -0
  110. package/ui/public/ask-panel.mjs +1880 -0
  111. package/ui/public/chat-settings-view.mjs +6 -2
  112. package/ui/public/diff-view.mjs +66 -11
  113. package/ui/public/file-tree.mjs +305 -0
  114. package/ui/public/graph/composer.mjs +889 -0
  115. package/ui/public/graph/inspector.mjs +183 -0
  116. package/ui/public/graph/model.mjs +37 -0
  117. package/ui/public/graph/palette.mjs +144 -0
  118. package/ui/public/graph/run-decor.mjs +410 -0
  119. package/ui/public/graph/run-hosts.mjs +201 -0
  120. package/ui/public/graph/save-dialog.mjs +56 -0
  121. package/ui/public/graph/view.mjs +858 -0
  122. package/ui/public/guardrails-view.mjs +4 -2
  123. package/ui/public/hljs-loader.mjs +180 -0
  124. package/ui/public/index.html +269 -265
  125. package/ui/public/log-filter.mjs +22 -4
  126. package/ui/public/log-line.mjs +45 -19
  127. package/ui/public/models-view.mjs +171 -9
  128. package/ui/public/plugins-view.mjs +106 -4
  129. package/ui/public/source-pane.mjs +190 -8
  130. package/ui/public/stats-view.mjs +81 -1
  131. package/ui/public/style.css +1459 -229
  132. package/ui/public/syntax-highlight.mjs +270 -0
  133. package/ui/public/thinking-orb.mjs +110 -0
  134. package/ui/server.mjs +1667 -98
  135. package/src/core/channels.mjs +0 -302
  136. package/src/core/runners.mjs +0 -167
  137. package/src/core/workflow-validator.mjs +0 -185
  138. package/ui/public/composer-core.mjs +0 -211
@@ -11,9 +11,15 @@
11
11
  <body>
12
12
  <div class="app">
13
13
  <!-- ===================== Sidebar ===================== -->
14
- <aside class="sidebar">
14
+ <aside class="sidebar" id="side-rail">
15
15
  <div class="brand">
16
16
  <img class="logo" src="/assets/worca-logo.png" alt="Worca" />
17
+ <img class="logo-mark" src="/assets/worca-favicon.png" alt="Worca" />
18
+ <button type="button" class="side-toggle" id="side-toggle"
19
+ aria-expanded="true" aria-controls="side-rail"
20
+ title="Collapse menu" aria-label="Collapse menu">
21
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2.5"></rect><path d="M9 3v18"></path><path class="chev" d="M16 15l-3-3 3-3"></path></svg>
22
+ </button>
17
23
  </div>
18
24
 
19
25
  <nav class="nav" aria-label="Primary">
@@ -52,18 +58,6 @@
52
58
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><circle cx="9" cy="8" r="3.2"></circle><path d="M3.5 19c.6-3 2.8-4.6 5.5-4.6S13.9 16 14.5 19"></path><circle cx="17.5" cy="9.5" r="2.4"></circle><path d="M15.5 14.6c2.7 0 4.4 1.4 5 4.4"></path></svg>
53
59
  <span>Agents</span>
54
60
  </button>
55
- <button type="button" data-nav="guardrails">
56
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3l7 3v5c0 4.6-3 8.4-7 10-4-1.6-7-5.4-7-10V6z"></path></svg>
57
- <span>Guardrails</span>
58
- </button>
59
- <button type="button" data-nav="models">
60
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><rect x="7" y="7" width="10" height="10" rx="2"></rect><path d="M12 2v3M12 19v3M2 12h3M19 12h3M6 2.5v2M18 2.5v2M6 19.5v2M18 19.5v2"></path></svg>
61
- <span>Models</span>
62
- </button>
63
- <button type="button" data-nav="plugins">
64
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M9 3v5M15 3v5M7 8h10v4a5 5 0 0 1-10 0V8Z"></path><path d="M12 17v4"></path></svg>
65
- <span>Plugins</span>
66
- </button>
67
61
 
68
62
  <div class="nav-sect">Manage</div>
69
63
  <button type="button" data-nav="projects">
@@ -101,9 +95,6 @@
101
95
  <span class="topnav-sep" aria-hidden="true"></span>
102
96
  <button type="button" data-nav="composer">Composer</button>
103
97
  <button type="button" data-nav="agents">Agents</button>
104
- <button type="button" data-nav="guardrails">Guardrails</button>
105
- <button type="button" data-nav="models">Models</button>
106
- <button type="button" data-nav="plugins">Plugins</button>
107
98
  <span class="topnav-sep" aria-hidden="true"></span>
108
99
  <button type="button" data-nav="projects">Projects</button>
109
100
  <button type="button" data-nav="workspaces">Workspaces</button>
@@ -389,6 +380,7 @@
389
380
  <div class="rc-meta">
390
381
  <span class="rc-status-word"></span>
391
382
  <span class="rc-seg"><span class="rc-dot">·</span><span class="rm-text"></span></span>
383
+ <span class="rc-seg rc-prog" hidden><span class="rc-dot">·</span><span class="rc-prog-text"></span></span>
392
384
  <span class="rc-seg"><span class="rc-dot">·</span><span class="run-time mono"></span></span>
393
385
  <span class="rc-seg"><span class="rc-dot">·</span><span class="run-cost mono"></span></span>
394
386
  </div>
@@ -423,7 +415,7 @@
423
415
  <div class="rc-detailed">
424
416
  <div class="run-flow-wrap"><div class="run-flow"></div></div>
425
417
  <div class="run-log">
426
- <div class="run-log-head"><span class="ll-label">Live log</span><div class="log-filters"><select class="log-f log-f-source" title="Filter by source" aria-label="Filter by source"></select><select class="log-f log-f-level" title="Filter by level" aria-label="Filter by level"></select><select class="log-f log-f-step" title="Filter by step" aria-label="Filter by step"></select><select class="log-f log-f-cycle" title="Filter by cycle" aria-label="Filter by cycle"></select><input type="search" class="log-f log-search" placeholder="search" title="Search the log text" aria-label="Search the log text"><button type="button" class="log-f log-copy" title="Copy the visible log lines" aria-label="Copy the visible log lines">copy</button></div><div class="switch-row"><div class="switch on autoscroll" role="switch" aria-checked="true" tabindex="0"></div><span class="txt">Auto-scroll</span></div></div>
418
+ <div class="run-log-head"><span class="ll-label">Live log</span><div class="log-filters"><select class="log-f log-f-source" title="Filter by source" aria-label="Filter by source"></select><select class="log-f log-f-level" title="Filter by level" aria-label="Filter by level"></select><select class="log-f log-f-step" title="Filter by step" aria-label="Filter by step"></select><select class="log-f log-f-cycle" title="Filter by cycle" aria-label="Filter by cycle"></select><button type="button" class="log-f log-f-exec" hidden title="Showing one execution — click to clear"><span class="lfe-text"></span><span class="lfe-x" aria-hidden="true">×</span></button><input type="search" class="log-f log-search" placeholder="search" title="Search the log text" aria-label="Search the log text"><button type="button" class="log-f log-copy" title="Copy the visible log lines" aria-label="Copy the visible log lines">copy</button></div><div class="switch-row"><div class="switch on autoscroll" role="switch" aria-checked="true" tabindex="0"></div><span class="txt">Auto-scroll</span></div></div>
427
419
  <div class="log"></div>
428
420
  </div>
429
421
  </div><!-- /.rc-detailed -->
@@ -546,6 +538,10 @@
546
538
  <span class="hist-diff mono" aria-label="lines changed"></span>
547
539
  <span class="hist-nodiff mono" hidden>no diff</span>
548
540
  </span>
541
+ <span class="hist-cmt-pill" hidden>
542
+ <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7"><path d="M21 12a8 8 0 0 1-8 8H7l-4 3v-6.5A8 8 0 0 1 11 4h2a8 8 0 0 1 8 8z" stroke-linejoin="round"></path></svg>
543
+ <span class="hist-cmt-count mono" aria-label="unresolved diff comments"></span>
544
+ </span>
549
545
  </div>
550
546
  <span class="hist-branch mono" hidden>
551
547
  <span class="hist-branch-src" hidden></span>
@@ -791,7 +787,7 @@
791
787
  <div class="topbar">
792
788
  <div>
793
789
  <h1>Agents</h1>
794
- <div class="sub">Built-in and custom agents — what each consumes and produces drives the Composer</div>
790
+ <div class="sub">Built-in and custom agents — the typed ports each one reads and writes drive the Composer</div>
795
791
  </div>
796
792
  <button type="button" id="agent-create-btn" class="btn-go" style="padding:11px 20px">
797
793
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round"><path d="M12 5v14M5 12h14"></path></svg>
@@ -807,6 +803,7 @@
807
803
  <div class="agent-h-meta">
808
804
  <b class="agent-name"></b>
809
805
  <span class="agent-origin badge"></span>
806
+ <span class="agent-not-placeable badge" hidden>not placeable</span>
810
807
  <small class="agent-sub"></small>
811
808
  <div class="agent-io">
812
809
  <div class="agent-io-row agent-io-in">
@@ -829,41 +826,7 @@
829
826
  <div class="agent-detail" hidden>
830
827
  <pre class="agent-md-view viewer"></pre>
831
828
  <div class="agent-edit-pane" hidden>
832
- <div class="field"><label>Display name</label><input class="agent-f-name input" type="text" spellcheck="false" /></div>
833
- <div class="field"><label>Description</label><input class="agent-f-desc input" type="text" spellcheck="false" /></div>
834
- <div class="row-2">
835
- <div class="field"><label>Color</label>
836
- <div class="select-wrap"><select class="agent-f-color select">
837
- <option>green</option><option>peach</option><option>red</option>
838
- <option>blue</option><option>violet</option><option>amber</option>
839
- </select></div>
840
- </div>
841
- <div class="field"><label>Runner type</label>
842
- <div class="select-wrap"><select class="agent-f-runner select">
843
- <option>producer</option><option>verifier</option>
844
- </select></div>
845
- </div>
846
- </div>
847
- <div class="field"><label>Consumes</label><div class="agent-f-consumes chip-select"></div></div>
848
- <div class="field"><label>Optional consumes</label><div class="agent-f-optional chip-select"></div></div>
849
- <div class="field"><label>Produces</label><div class="agent-f-produces chip-select"></div></div>
850
- <div class="field"><label>Connects to</label>
851
- <label class="fanout-toggle"><input type="checkbox" class="agent-f-connect-any" /><span>any agent (*)</span></label>
852
- <div class="agent-f-connects chip-select"></div>
853
- </div>
854
- <div class="row-2">
855
- <div class="field"><label>Order</label><input class="agent-f-order input" type="number" step="0.1" /></div>
856
- <div class="field"><label>Flags</label>
857
- <label class="fanout-toggle"><input type="checkbox" class="agent-f-fanout" /><span>Fan-out</span></label>
858
- <label class="fanout-toggle"><input type="checkbox" class="agent-f-loopsource" /><span>Loop source</span></label>
859
- <label class="fanout-toggle"><input type="checkbox" class="agent-f-questions" /><span>Asks questions</span></label>
860
- <label class="fanout-toggle"><input type="checkbox" class="agent-f-questions-locked" /><span>Questions locked</span></label>
861
- <label class="fanout-toggle"><input type="checkbox" class="agent-f-questions-default" /><span>Questions on by default</span></label>
862
- </div>
863
- </div>
864
- <div class="field"><label>System prompt (markdown)</label>
865
- <textarea class="agent-f-md textarea" rows="16" spellcheck="false"></textarea>
866
- </div>
829
+ <div class="agent-form"></div>
867
830
  <p class="agent-edit-msg form-msg" aria-live="polite"></p>
868
831
  <div class="actions" style="justify-content:flex-end">
869
832
  <button type="button" class="agent-edit-cancel btn btn-ghost btn-mini">Cancel</button>
@@ -876,71 +839,6 @@
876
839
  </section>
877
840
  <!-- /view agents -->
878
841
 
879
- <!-- ===== VIEW: PLUGINS ===== -->
880
- <section class="view hidden" data-view="plugins">
881
- <div class="topbar">
882
- <div>
883
- <h1>Plugins</h1>
884
- <div class="sub">Task sources, agents, skills and workflow packs from your plugin marketplaces</div>
885
- </div>
886
- <button type="button" id="plugin-add-btn" class="btn-go" style="padding:11px 20px">
887
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round"><path d="M12 5v14M5 12h14"></path></svg>
888
- Add marketplace
889
- </button>
890
- </div>
891
- <p id="plugins-msg" class="form-msg" aria-live="polite"></p>
892
- <div class="card hidden" id="marketplace-add-row" style="padding:16px 20px;margin-bottom:14px">
893
- <div class="path-row">
894
- <input id="marketplace-url" class="input" type="text" placeholder="https://github.com/owner/repo · owner/repo · /abs/path/to/repo" spellcheck="false" />
895
- <button type="button" id="marketplace-add" class="btn btn-primary btn-mini">Add</button>
896
- </div>
897
- </div>
898
- <h3 class="pl-sec-title">Installed</h3>
899
- <div class="run-list" id="plugins-list"></div>
900
- <h3 class="pl-sec-title">Available</h3>
901
- <div class="run-list" id="plugins-available"></div>
902
- <h3 class="pl-sec-title">Marketplaces</h3>
903
- <div class="run-list" id="marketplaces-list"></div>
904
- </section>
905
- <!-- /view plugins -->
906
-
907
- <!-- ===== VIEW: GUARDRAILS ===== -->
908
- <section class="view hidden" data-view="guardrails">
909
- <div class="topbar">
910
- <div>
911
- <h1>Guardrails</h1>
912
- <div class="sub">Named guardrail policies — built-ins plus your own sets, selected per pipeline run</div>
913
- </div>
914
- <button type="button" id="guardrail-create-btn" class="btn-go" style="padding:11px 20px">
915
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round"><path d="M12 5v14M5 12h14"></path></svg>
916
- Create guardrails
917
- </button>
918
- </div>
919
- <p id="guardrails-msg" class="form-msg" aria-live="polite"></p>
920
- <div class="run-list" id="guardrails-list"></div>
921
- </section>
922
- <!-- /view guardrails -->
923
-
924
- <!-- ===== VIEW: MODELS ===== -->
925
- <section class="view hidden" data-view="models">
926
- <div class="topbar">
927
- <div>
928
- <h1>Models</h1>
929
- <div class="sub">Global model catalog — available in every project; entries can override built-ins and carry per-model routing env</div>
930
- </div>
931
- <div style="display:flex;gap:8px">
932
- <button type="button" id="model-share-btn" class="btn-ghost" style="padding:11px 20px">Share as plugin…</button>
933
- <button type="button" id="model-create-btn" class="btn-go" style="padding:11px 20px">
934
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round"><path d="M12 5v14M5 12h14"></path></svg>
935
- Add model
936
- </button>
937
- </div>
938
- </div>
939
- <p id="models-msg" class="form-msg" aria-live="polite"></p>
940
- <div class="run-list" id="models-list"></div>
941
- </section>
942
- <!-- /view models -->
943
-
944
842
  <!-- ===== VIEW: PROJECTS ===== -->
945
843
  <section class="view hidden" data-view="projects">
946
844
  <div class="topbar">
@@ -1012,29 +910,7 @@
1012
910
 
1013
911
  <!-- Step 3: review/edit draft (shared agent-f-* form classes) -->
1014
912
  <div class="wiz-step hidden" id="agw-step-3">
1015
- <div class="field"><label>Display name</label><input class="agent-f-name input" type="text" spellcheck="false" /></div>
1016
- <div class="field"><label>Description</label><input class="agent-f-desc input" type="text" spellcheck="false" /></div>
1017
- <div class="row-2">
1018
- <div class="field"><label>Color</label><div class="select-wrap"><select class="agent-f-color select"><option>green</option><option>peach</option><option>red</option><option>blue</option><option>violet</option><option>amber</option></select></div></div>
1019
- <div class="field"><label>Runner type</label><div class="select-wrap"><select class="agent-f-runner select"><option>producer</option><option>verifier</option></select></div></div>
1020
- </div>
1021
- <div class="field"><label>Consumes</label><div class="agent-f-consumes chip-select"></div></div>
1022
- <div class="field"><label>Optional consumes</label><div class="agent-f-optional chip-select"></div></div>
1023
- <div class="field"><label>Produces</label><div class="agent-f-produces chip-select"></div></div>
1024
- <div class="field"><label>Connects to</label>
1025
- <label class="fanout-toggle"><input type="checkbox" class="agent-f-connect-any" /><span>any agent (*)</span></label>
1026
- <div class="agent-f-connects chip-select"></div></div>
1027
- <div class="row-2">
1028
- <div class="field"><label>Order</label><input class="agent-f-order input" type="number" step="0.1" /></div>
1029
- <div class="field"><label>Flags</label>
1030
- <label class="fanout-toggle"><input type="checkbox" class="agent-f-fanout" /><span>Fan-out</span></label>
1031
- <label class="fanout-toggle"><input type="checkbox" class="agent-f-loopsource" /><span>Loop source</span></label>
1032
- <label class="fanout-toggle"><input type="checkbox" class="agent-f-questions" /><span>Asks questions</span></label>
1033
- <label class="fanout-toggle"><input type="checkbox" class="agent-f-questions-locked" /><span>Questions locked</span></label>
1034
- <label class="fanout-toggle"><input type="checkbox" class="agent-f-questions-default" /><span>Questions on by default</span></label></div>
1035
- </div>
1036
- <div class="field"><label>System prompt (markdown)</label>
1037
- <textarea class="agent-f-md textarea" rows="16" spellcheck="false"></textarea></div>
913
+ <div class="agent-form"></div>
1038
914
  <p id="agw-msg" class="form-msg" aria-live="polite"></p>
1039
915
  <div class="actions" style="justify-content:space-between">
1040
916
  <button type="button" id="agw-regen" class="btn btn-ghost btn-mini">Regenerate</button>
@@ -1048,169 +924,295 @@
1048
924
  </section>
1049
925
  <!-- /view agent-create -->
1050
926
 
1051
- <!-- ===== VIEW: WORKFLOW COMPOSER ===== -->
927
+ <!-- ===== VIEW: WORKFLOW COMPOSER (v2 node graph) ===== -->
1052
928
  <section class="view hidden" data-view="composer">
1053
929
  <div class="topbar">
1054
930
  <div>
1055
931
  <h1>Workflow Composer</h1>
1056
- <div class="sub">Compose how your agents collaborate — drag, stack, and loop them into a workflow</div>
1057
932
  </div>
1058
- <button type="button" class="btn-ghost" id="composer-reset" style="padding:11px 20px">Reset to default</button>
1059
933
  </div>
1060
934
 
1061
- <section class="card builder-card">
1062
- <div class="palette">
1063
- <span class="p-label">
1064
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="6" cy="6" r="2"></circle><circle cx="6" cy="18" r="2"></circle><circle cx="18" cy="6" r="2"></circle><circle cx="18" cy="18" r="2"></circle></svg>
1065
- Agents · drag onto the canvas to build your workflow
1066
- <input id="composer-agent-filter" class="pal-filter" type="search" placeholder="Filter agents…" aria-label="Filter agents by name or description">
1067
- </span>
1068
- <div id="composer-palette" style="display:contents"></div>
935
+ <section class="card gv-editor">
936
+ <div class="gv-head" id="gv-head">
937
+ <input id="gv-name" class="gv-name" type="text" spellcheck="false" placeholder="Untitled pipeline" aria-label="Pipeline name">
938
+ <button type="button" class="gv-errchip" id="gv-errors" hidden></button>
939
+ <span class="sp"></span>
940
+ <button type="button" class="btn-ghost" id="gv-new">New canvas</button>
941
+ <button type="button" class="btn-ghost" id="gv-autolayout">Auto-layout</button>
942
+ <button type="button" class="btn-go" id="gv-save">Save</button>
1069
943
  </div>
1070
-
1071
- <div class="canvas-wrap" id="composer-canvas-wrap">
1072
- <div id="composer-decomposer-hint" class="composer-hint" hidden>
1073
- When a Decompose step is present, 1 implementer is started per task it produces the count varies per run.
1074
- </div>
1075
- <div class="flow" id="composer-flow">
1076
- <svg class="wires" id="composer-wires"></svg>
944
+ <!-- The stage is created INSIDE #gv-canvas by createGraphView. The chip
945
+ and the inspector rail are its SIBLINGS: a pointerdown on them can
946
+ never reach the stage, so capture can never retarget their click.
947
+ The rail carries BOTH panes the agent palette and the inspector
948
+ switched by `data-tab`; `data-open` still collapses the whole rail. -->
949
+ <div class="gv-canvas" id="gv-canvas">
950
+ <div class="gv-chip" id="gv-chip" hidden></div>
951
+ <div class="gv-ins-rail" id="gv-ins-rail" data-open="open" data-tab="agents">
952
+ <div class="gv-ins-bar">
953
+ <button type="button" class="gv-ins-toggle" id="gv-ins-toggle" aria-expanded="true" aria-label="Collapse inspector"><svg class="chev" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M9 6l6 6-6 6" stroke-linecap="round" stroke-linejoin="round"></path></svg></button>
954
+ <div class="gv-tabs" id="gv-ins-tabs" role="tablist" aria-label="Rail panes">
955
+ <button type="button" class="gv-tab" role="tab" data-tab="agents" aria-selected="true">Agents</button>
956
+ <button type="button" class="gv-tab" role="tab" data-tab="info" aria-selected="false" tabindex="-1">Info</button>
957
+ </div>
958
+ </div>
959
+ <div class="gv-ins-pane gv-agents-pane" id="gv-agents-pane">
960
+ <div class="gv-pal-head">
961
+ <input id="gv-agent-filter" class="pal-filter" type="search" placeholder="Filter agents…" aria-label="Filter agents by name or ports">
962
+ </div>
963
+ <div class="gv-palette" id="gv-palette"></div>
964
+ </div>
965
+ <div class="gv-ins-pane gv-ins-body" id="gv-ins-body"></div>
1077
966
  </div>
1078
967
  </div>
1079
-
1080
- <div class="builder-foot">
1081
- <div class="legend">
1082
- <span class="lg"><span class="ll"></span> sequential runs in order</span>
1083
- <span class="lg"><span class="ll fb"></span> feedback loop</span>
1084
- <span class="lg"><span class="ll sl"></span> self loop</span>
1085
- </div>
1086
- <span class="link-banner" id="composer-link-banner" hidden>
1087
- <span id="composer-link-text">Click a target agent to draw a feedback loop</span>
1088
- <button type="button" id="composer-link-cancel">Cancel</button>
1089
- </span>
1090
- <span class="sp"></span>
1091
- <button type="button" class="btn-ghost" id="composer-clear" style="padding:10px 18px">Clear canvas</button>
1092
- <button type="button" class="btn-go" id="composer-save">
1093
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4"><path d="M5 13l4 4L19 7" stroke-linecap="round" stroke-linejoin="round"></path></svg>
1094
- Save workflow
1095
- </button>
968
+ <!-- The key belongs to the whole editor, canvas AND rail — not to a
969
+ palette card that no longer exists. -->
970
+ <div class="gv-foot">
971
+ <span class="gv-legend" id="gv-legend">grey = data · amber = loop · ◆ = conditional · ○ = gate · ⤫N = fan-out</span>
1096
972
  </div>
1097
973
  </section>
1098
974
 
1099
- <section class="card saved-card">
975
+ <section class="card gv-saved">
1100
976
  <div class="saved-head">
1101
- <div><b>Saved workflows</b><span class="cnt" id="composer-saved-count"></span></div>
977
+ <div><b>Saved pipelines</b><span class="cnt" id="gv-saved-count"></span></div>
1102
978
  </div>
1103
- <div class="saved-list" id="composer-saved-list"></div>
979
+ <div class="saved-list" id="gv-saved-list"></div>
980
+ <div class="gv-archived" id="gv-archived" hidden></div>
981
+ <!-- A refused DELETE (the built-in, a 404, a 500) has to land
982
+ SOMEWHERE: same .form-msg line every other list view uses. -->
983
+ <p id="gv-saved-msg" class="form-msg" aria-live="polite"></p>
1104
984
  </section>
985
+ <div id="gv-dialog-host"></div>
1105
986
  </section>
1106
987
  <!-- /view composer -->
1107
988
 
1108
- <!-- ===== VIEW: SETTINGS ===== -->
989
+ <!-- ===== VIEW: SETTINGS (tabbed) =====
990
+ Guardrails / Models / Plugins used to be top-level views; they are
991
+ now panes here. A pane deliberately carries NEITHER class="view" nor
992
+ the routing attribute: showView()'s views.forEach() would force
993
+ .hidden back on it at every navigation. The tab rides in the hash
994
+ param (#settings/<tab>, #settings/guardrails/<id>) — parseHash splits
995
+ on the FIRST '/' only, so the view stays 'settings'.
996
+ NOTE: the routed-view census in test/ui-shell.test.mjs counts the
997
+ literal routing attribute name, so never spell it out in a comment. -->
1109
998
  <section class="view hidden" data-view="settings">
1110
- <div class="topbar">
1111
- <div>
1112
- <h1>Settings</h1>
1113
- <div class="sub">Machine-wide Worca CC preferences</div>
1114
- </div>
999
+ <div class="seg settings-tabs" id="settings-tabs" role="group" aria-label="Settings section">
1000
+ <button type="button" class="on" data-tab="general" aria-pressed="true">General</button>
1001
+ <button type="button" data-tab="guardrails" aria-pressed="false">Guardrails</button>
1002
+ <button type="button" data-tab="models" aria-pressed="false">Models</button>
1003
+ <button type="button" data-tab="plugins" aria-pressed="false">Plugins</button>
1115
1004
  </div>
1116
1005
 
1117
- <section class="card settings-card">
1118
- <div class="field">
1119
- <div class="label-row">
1120
- <label for="settingsRoot">Worca CC root folder</label>
1121
- <button type="button" class="info-tip" aria-label="About Worca CC root folder">i<span class="tip-content hidden">
1122
- The folder under which Worca CC keeps its data &mdash; a <code>.worca-cc/</code> directory holding the
1123
- history store, the project list, and saved workflows. Leave empty to use the default.
1124
- Changes apply to new runs immediately. Changing the root does <b>not</b> move existing
1125
- data: Worca CC starts a fresh <code>.worca-cc/</code> under the new folder; history under
1126
- the old root is left in place.
1127
- </span></button>
1006
+ <section class="settings-pane" data-tab="general">
1007
+ <div class="topbar">
1008
+ <div>
1009
+ <h1>Settings</h1>
1010
+ <div class="sub">Machine-wide Worca CC preferences</div>
1128
1011
  </div>
1129
- <input id="settingsRoot" class="input" type="text" placeholder="" spellcheck="false" autocomplete="off" />
1130
1012
  </div>
1131
- <div class="field">
1132
- <div class="label-row">
1133
- <label for="settingsProjectsRoot">Projects root folder</label>
1134
- <button type="button" class="info-tip" aria-label="About Projects root folder">i<span class="tip-content hidden">
1135
- The top-level folder under which your projects live. Its CLAUDE.md, .claude/skills, and
1136
- .mcp.json are made available to every pipeline agent. Leave empty to use your home folder.
1137
- </span></button>
1013
+
1014
+ <section class="card settings-card">
1015
+ <div class="field">
1016
+ <div class="label-row">
1017
+ <label for="settingsRoot">Worca CC root folder</label>
1018
+ <button type="button" class="info-tip" aria-label="About Worca CC root folder">i<span class="tip-content hidden">
1019
+ The folder under which Worca CC keeps its data &mdash; a <code>.worca-cc/</code> directory holding the
1020
+ history store, the project list, and saved workflows. Leave empty to use the default.
1021
+ Changes apply to new runs immediately. Changing the root does <b>not</b> move existing
1022
+ data: Worca CC starts a fresh <code>.worca-cc/</code> under the new folder; history under
1023
+ the old root is left in place.
1024
+ </span></button>
1025
+ </div>
1026
+ <input id="settingsRoot" class="input" type="text" placeholder="" spellcheck="false" autocomplete="off" />
1138
1027
  </div>
1139
- <div class="path-row">
1140
- <input id="settingsProjectsRoot" class="input" type="text" placeholder="" spellcheck="false" autocomplete="off" />
1141
- <button type="button" id="settingsProjectsRootBrowse" class="btn btn-ghost btn-mini" title="Pick the projects root folder">Browse&hellip;</button>
1028
+ <div class="field">
1029
+ <div class="label-row">
1030
+ <label for="settingsProjectsRoot">Projects root folder</label>
1031
+ <button type="button" class="info-tip" aria-label="About Projects root folder">i<span class="tip-content hidden">
1032
+ The top-level folder under which your projects live. Its CLAUDE.md, .claude/skills, and
1033
+ .mcp.json are made available to every pipeline agent. Leave empty to use your home folder.
1034
+ </span></button>
1035
+ </div>
1036
+ <div class="path-row">
1037
+ <input id="settingsProjectsRoot" class="input" type="text" placeholder="" spellcheck="false" autocomplete="off" />
1038
+ <button type="button" id="settingsProjectsRootBrowse" class="btn btn-ghost btn-mini" title="Pick the projects root folder">Browse&hellip;</button>
1039
+ </div>
1142
1040
  </div>
1143
- </div>
1144
- <div class="add-project-actions" style="margin-top:14px">
1145
- <button type="button" id="settingsReset" class="btn btn-ghost btn-mini">Reset to default</button>
1146
- <button type="button" id="settingsSave" class="btn btn-primary btn-mini">Save</button>
1147
- </div>
1148
- <small class="hint" id="settingsMsg"></small>
1149
- </section>
1041
+ <div class="add-project-actions" style="margin-top:14px">
1042
+ <button type="button" id="settingsReset" class="btn btn-ghost btn-mini">Reset to default</button>
1043
+ <button type="button" id="settingsSave" class="btn btn-primary btn-mini">Save</button>
1044
+ </div>
1045
+ <small class="hint" id="settingsMsg"></small>
1046
+ </section>
1150
1047
 
1151
- <section class="card settings-card">
1152
- <div class="card-head">
1153
- <div class="label-row">
1154
- <h2>Budget &amp; cost limits</h2>
1155
- <button type="button" class="info-tip" aria-label="About budget costs">i<span class="tip-content hidden">
1156
- Costs are Claude Code's client-side estimate (total_cost_usd), not authoritative billing.
1157
- </span></button>
1048
+ <section class="card settings-card">
1049
+ <div class="card-head">
1050
+ <div class="label-row">
1051
+ <h2>Budget &amp; cost limits</h2>
1052
+ <button type="button" class="info-tip" aria-label="About budget costs">i<span class="tip-content hidden">
1053
+ Costs are Claude Code's client-side estimate (total_cost_usd), not authoritative billing.
1054
+ </span></button>
1055
+ </div>
1158
1056
  </div>
1159
- </div>
1160
- <div id="budgetReadout"></div>
1161
- <div class="field">
1162
- <div class="label-row">
1163
- <label for="budgetPerPipeline">Per-pipeline cost limit (USD)</label>
1164
- <button type="button" class="info-tip" aria-label="About Per-pipeline cost limit">i<span class="tip-content hidden">
1165
- Pause a pipeline when its estimated cost reaches this amount. Leave empty for no limit.
1166
- </span></button>
1057
+ <div id="budgetReadout"></div>
1058
+ <div class="field">
1059
+ <div class="label-row">
1060
+ <label for="budgetPerPipeline">Per-pipeline cost limit (USD)</label>
1061
+ <button type="button" class="info-tip" aria-label="About Per-pipeline cost limit">i<span class="tip-content hidden">
1062
+ Pause a pipeline when its estimated cost reaches this amount. Leave empty for no limit.
1063
+ </span></button>
1064
+ </div>
1065
+ <input id="budgetPerPipeline" class="input" type="number" min="0" step="0.01" inputmode="decimal" placeholder="No limit" autocomplete="off" />
1167
1066
  </div>
1168
- <input id="budgetPerPipeline" class="input" type="number" min="0" step="0.01" inputmode="decimal" placeholder="No limit" autocomplete="off" />
1169
- </div>
1170
- <div class="field">
1171
- <div class="label-row">
1172
- <label for="budgetTotal">Total cost limit (USD)</label>
1173
- <button type="button" class="info-tip" aria-label="About Total cost limit">i<span class="tip-content hidden">
1174
- Pause all pipelines and block new ones when total spend in the period reaches this amount.
1175
- Leave empty for no limit.
1176
- </span></button>
1067
+ <div class="field">
1068
+ <div class="label-row">
1069
+ <label for="budgetTotal">Total cost limit (USD)</label>
1070
+ <button type="button" class="info-tip" aria-label="About Total cost limit">i<span class="tip-content hidden">
1071
+ Pause all pipelines and block new ones when total spend in the period reaches this amount.
1072
+ Leave empty for no limit.
1073
+ </span></button>
1074
+ </div>
1075
+ <input id="budgetTotal" class="input" type="number" min="0" step="0.01" inputmode="decimal" placeholder="No limit" autocomplete="off" />
1177
1076
  </div>
1178
- <input id="budgetTotal" class="input" type="number" min="0" step="0.01" inputmode="decimal" placeholder="No limit" autocomplete="off" />
1179
- </div>
1180
- <div class="field">
1077
+ <div class="field">
1078
+ <div class="label-row">
1079
+ <label for="budgetResetPeriod">Reset period</label>
1080
+ <button type="button" class="info-tip" aria-label="About Reset period">i<span class="tip-content hidden">
1081
+ Spend counts within the current period and returns to $0.00 at the reset. Times are local.
1082
+ </span></button>
1083
+ </div>
1084
+ <div class="select-wrap">
1085
+ <select id="budgetResetPeriod" class="select">
1086
+ <option value="weekly">Weekly &mdash; resets Monday 00:00</option>
1087
+ <option value="monthly">Monthly &mdash; resets on the 1st, 00:00</option>
1088
+ </select>
1089
+ </div>
1090
+ </div>
1091
+ <div class="add-project-actions" style="margin-top:14px">
1092
+ <button type="button" id="budgetReset" class="btn btn-ghost btn-mini">Clear limits</button>
1093
+ <button type="button" id="budgetSave" class="btn btn-primary btn-mini">Save</button>
1094
+ </div>
1095
+ <small class="hint" id="budgetMsg"></small>
1096
+ </section>
1097
+
1098
+ <!-- Ask Worca (ask-worca-design §6.9): per-turn guards for the
1099
+ assistant chat. Read fresh on every turn (D12); a stored null
1100
+ budget means "no cap". Posted ALONE — never with root/budget keys. -->
1101
+ <section class="card settings-card">
1102
+ <div class="card-head">
1103
+ <div class="label-row">
1104
+ <h2>Ask Worca</h2>
1105
+ <button type="button" class="info-tip" aria-label="About Ask Worca limits">i<span class="tip-content hidden">
1106
+ Per-turn guards for the Ask Worca assistant chat. A chat turn stops when it reaches the turn limit or the per-turn cost cap; both are read fresh on every turn.
1107
+ </span></button>
1108
+ </div>
1109
+ </div>
1110
+ <div class="field">
1111
+ <div class="label-row">
1112
+ <label for="askMaxTurns">Turn limit</label>
1113
+ <button type="button" class="info-tip" aria-label="About Turn limit">i<span class="tip-content hidden">
1114
+ Maximum assistant/tool turns one chat message may use (1&ndash;500). Leave empty to restore the default of 40.
1115
+ </span></button>
1116
+ </div>
1117
+ <input id="askMaxTurns" class="input" type="number" min="1" max="500" step="1" inputmode="numeric" placeholder="40" autocomplete="off" />
1118
+ </div>
1119
+ <div class="field">
1120
+ <div class="label-row">
1121
+ <label for="askMaxBudgetUsd">Per-turn cost cap (USD)</label>
1122
+ <button type="button" class="info-tip" aria-label="About Per-turn cost cap">i<span class="tip-content hidden">
1123
+ Stop a chat turn when its estimated cost reaches this amount (0.1&ndash;100). Leave empty to restore the default of $2, or tick No cap to disable the guard.
1124
+ </span></button>
1125
+ </div>
1126
+ <input id="askMaxBudgetUsd" class="input" type="number" min="0.1" max="100" step="0.1" inputmode="decimal" placeholder="2" autocomplete="off" />
1127
+ <label class="check-row" for="askNoCap"><input id="askNoCap" type="checkbox" /> No cap</label>
1128
+ </div>
1129
+ <div class="add-project-actions" style="margin-top:14px">
1130
+ <button type="button" id="askLimitsReset" class="btn btn-ghost btn-mini">Use defaults</button>
1131
+ <button type="button" id="askLimitsSave" class="btn btn-primary btn-mini">Save</button>
1132
+ </div>
1133
+ <small class="hint" id="askLimitsMsg"></small>
1134
+ </section>
1135
+
1136
+ <!-- Chat notifications (chat-connectivity-design.md §4.8): which run
1137
+ events ping which chat channels. Body rendered by
1138
+ chat-settings-view.mjs; app.js owns fetch/save/Test wiring. -->
1139
+ <section class="card settings-card" id="chat-settings-card">
1181
1140
  <div class="label-row">
1182
- <label for="budgetResetPeriod">Reset period</label>
1183
- <button type="button" class="info-tip" aria-label="About Reset period">i<span class="tip-content hidden">
1184
- Spend counts within the current period and returns to $0.00 at the reset. Times are local.
1185
- </span></button>
1141
+ <h2>Chat notifications</h2>
1142
+ </div>
1143
+ <div id="chat-settings-host"></div>
1144
+ <div class="add-project-actions" style="margin-top:14px">
1145
+ <button id="chatSettingsSave" class="btn btn-primary btn-mini" type="button">Save</button>
1186
1146
  </div>
1187
- <div class="select-wrap">
1188
- <select id="budgetResetPeriod" class="select">
1189
- <option value="weekly">Weekly &mdash; resets Monday 00:00</option>
1190
- <option value="monthly">Monthly &mdash; resets on the 1st, 00:00</option>
1191
- </select>
1147
+ <small class="hint" id="chatSettingsMsg"></small>
1148
+ </section>
1149
+ </section>
1150
+ <!-- /pane general -->
1151
+
1152
+ <!-- ===== TAB: GUARDRAILS (was the top-level Guardrails view) ===== -->
1153
+ <section class="settings-pane hidden" data-tab="guardrails">
1154
+ <div class="topbar">
1155
+ <div>
1156
+ <h1>Guardrails</h1>
1157
+ <div class="sub">Named guardrail policies — built-ins plus your own sets, selected per pipeline run</div>
1192
1158
  </div>
1159
+ <button type="button" id="guardrail-create-btn" class="btn-go" style="padding:11px 20px">
1160
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round"><path d="M12 5v14M5 12h14"></path></svg>
1161
+ Create guardrails
1162
+ </button>
1193
1163
  </div>
1194
- <div class="add-project-actions" style="margin-top:14px">
1195
- <button type="button" id="budgetReset" class="btn btn-ghost btn-mini">Clear limits</button>
1196
- <button type="button" id="budgetSave" class="btn btn-primary btn-mini">Save</button>
1164
+ <p id="guardrails-msg" class="form-msg" aria-live="polite"></p>
1165
+ <div class="run-list" id="guardrails-list"></div>
1166
+ </section>
1167
+ <!-- /pane guardrails -->
1168
+
1169
+ <!-- ===== TAB: MODELS (was the top-level Models view) ===== -->
1170
+ <section class="settings-pane hidden" data-tab="models">
1171
+ <div class="topbar">
1172
+ <div>
1173
+ <h1>Models</h1>
1174
+ <div class="sub">Global model catalog — available in every project; entries can override built-ins and carry per-model routing env</div>
1175
+ </div>
1176
+ <div style="display:flex;gap:8px">
1177
+ <button type="button" id="model-share-btn" class="btn-ghost" style="padding:11px 20px">Share as plugin…</button>
1178
+ <button type="button" id="model-create-btn" class="btn-go" style="padding:11px 20px">
1179
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round"><path d="M12 5v14M5 12h14"></path></svg>
1180
+ Add model
1181
+ </button>
1182
+ </div>
1197
1183
  </div>
1198
- <small class="hint" id="budgetMsg"></small>
1184
+ <p id="models-msg" class="form-msg" aria-live="polite"></p>
1185
+ <div class="run-list" id="models-list"></div>
1199
1186
  </section>
1200
-
1201
- <!-- Chat notifications (chat-connectivity-design.md §4.8): which run
1202
- events ping which chat channels. Body rendered by
1203
- chat-settings-view.mjs; app.js owns fetch/save/Test wiring. -->
1204
- <section class="card settings-card" id="chat-settings-card">
1205
- <div class="label-row">
1206
- <h2>Chat notifications</h2>
1187
+ <!-- /pane models -->
1188
+
1189
+ <!-- ===== TAB: PLUGINS (was the top-level Plugins view) ===== -->
1190
+ <section class="settings-pane hidden" data-tab="plugins">
1191
+ <div class="topbar">
1192
+ <div>
1193
+ <h1>Plugins</h1>
1194
+ <div class="sub">Task sources, agents, skills and workflow packs from your plugin marketplaces</div>
1195
+ </div>
1196
+ <button type="button" id="plugin-add-btn" class="btn-go" style="padding:11px 20px">
1197
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round"><path d="M12 5v14M5 12h14"></path></svg>
1198
+ Add marketplace
1199
+ </button>
1207
1200
  </div>
1208
- <div id="chat-settings-host"></div>
1209
- <div class="add-project-actions" style="margin-top:14px">
1210
- <button id="chatSettingsSave" class="btn btn-primary btn-mini" type="button">Save</button>
1201
+ <p id="plugins-msg" class="form-msg" aria-live="polite"></p>
1202
+ <div class="card hidden" id="marketplace-add-row" style="padding:16px 20px;margin-bottom:14px">
1203
+ <div class="path-row">
1204
+ <input id="marketplace-url" class="input" type="text" placeholder="https://github.com/owner/repo · owner/repo · /abs/path/to/repo" spellcheck="false" />
1205
+ <button type="button" id="marketplace-add" class="btn btn-primary btn-mini">Add</button>
1206
+ </div>
1211
1207
  </div>
1212
- <small class="hint" id="chatSettingsMsg"></small>
1208
+ <h3 class="pl-sec-title">Installed</h3>
1209
+ <div class="run-list" id="plugins-list"></div>
1210
+ <h3 class="pl-sec-title">Available</h3>
1211
+ <div class="run-list" id="plugins-available"></div>
1212
+ <h3 class="pl-sec-title">Marketplaces</h3>
1213
+ <div class="run-list" id="marketplaces-list"></div>
1213
1214
  </section>
1215
+ <!-- /pane plugins -->
1214
1216
  </section>
1215
1217
  <!-- /view settings -->
1216
1218
  </main>
@@ -1254,6 +1256,8 @@
1254
1256
  <h2 id="confirm-title">Confirm</h2>
1255
1257
  </div>
1256
1258
  <p id="confirm-message" class="confirm-message"></p>
1259
+ <!-- promptModal fills this with .confirm-field rows; empty for a plain confirm -->
1260
+ <div id="confirm-fields"></div>
1257
1261
  <label id="confirm-checkbox-wrap" class="confirm-checkbox hidden">
1258
1262
  <input type="checkbox" id="confirm-checkbox" />
1259
1263
  <span id="confirm-checkbox-label"></span>