@celsoft/coordinator 0.0.0 → 0.1.0

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 (131) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +107 -0
  3. package/THIRD_PARTY_NOTICES.md +2005 -0
  4. package/agents/console.md +20 -0
  5. package/agents/free.md +110 -0
  6. package/build/0-JP6XL6LB.js +17 -0
  7. package/build/1-A52YZWNS.js +17 -0
  8. package/build/2-CLH2NM6F.js +32 -0
  9. package/build/3-4N467IB6.js +45 -0
  10. package/build/4-WL5H4LUW.js +29 -0
  11. package/build/_layout.svelte-KPUSX7LQ.js +27 -0
  12. package/build/_page.svelte-22H56UR6.js +7972 -0
  13. package/build/_page.svelte-CVWUNRQC.js +135 -0
  14. package/build/_page.svelte-LTZXBHMT.js +57 -0
  15. package/build/_server.ts-3KVBYN6P.js +20 -0
  16. package/build/_server.ts-3POPKVEM.js +47 -0
  17. package/build/_server.ts-5735T2V5.js +31 -0
  18. package/build/_server.ts-5VXGNWV2.js +38 -0
  19. package/build/_server.ts-645KP7WP.js +42 -0
  20. package/build/_server.ts-A3AA24Z2.js +28 -0
  21. package/build/_server.ts-CITUOEM6.js +58 -0
  22. package/build/_server.ts-I7HMTPOA.js +25 -0
  23. package/build/_server.ts-M5BQ4LLX.js +30 -0
  24. package/build/_server.ts-OB4O27HF.js +683 -0
  25. package/build/_server.ts-OJT7HE7M.js +15 -0
  26. package/build/_server.ts-OYGWVLZM.js +12 -0
  27. package/build/_server.ts-T75UVMQP.js +38 -0
  28. package/build/_server.ts-WYZYNHUZ.js +28 -0
  29. package/build/_server.ts-Z26EB47B.js +486 -0
  30. package/build/chunk-4CIG53L5.js +33 -0
  31. package/build/chunk-BJTJS3XY.js +338 -0
  32. package/build/chunk-F2CNWJZM.js +14 -0
  33. package/build/chunk-HGYE3UTU.js +416 -0
  34. package/build/chunk-KAYW2W7H.js +1311 -0
  35. package/build/chunk-LFP3UPCM.js +10 -0
  36. package/build/chunk-M44JEFEH.js +62 -0
  37. package/build/chunk-MC5AGLMY.js +39 -0
  38. package/build/chunk-NCZ77J5E.js +19798 -0
  39. package/build/chunk-NVNLDPUJ.js +2122 -0
  40. package/build/chunk-PDCON4KS.js +494 -0
  41. package/build/chunk-Q4OQNY5M.js +25 -0
  42. package/build/chunk-QCUOR2U5.js +75 -0
  43. package/build/chunk-R6RYZZWA.js +46 -0
  44. package/build/chunk-SOJTASZC.js +51 -0
  45. package/build/chunk-SU26PJVX.js +410 -0
  46. package/build/chunk-U5BSBG4R.js +506 -0
  47. package/build/chunk-UEKOZGRO.js +37 -0
  48. package/build/chunk-W6EFUWJ2.js +9 -0
  49. package/build/chunk-WOPREK6Q.js +117 -0
  50. package/build/chunk-WWJ3F4QS.js +127 -0
  51. package/build/chunk-ZGZJEEE3.js +1091 -0
  52. package/build/client/_app/immutable/assets/0.BGa5ZNDM.css +1 -0
  53. package/build/client/_app/immutable/chunks/BUrrLYDt.js +2 -0
  54. package/build/client/_app/immutable/chunks/BgFr_EyZ.js +4 -0
  55. package/build/client/_app/immutable/chunks/Bjy-W4x2.js +82 -0
  56. package/build/client/_app/immutable/chunks/C8qZab0y.js +56 -0
  57. package/build/client/_app/immutable/chunks/C90fLsA5.js +4 -0
  58. package/build/client/_app/immutable/chunks/CRzLMJPS.js +1 -0
  59. package/build/client/_app/immutable/chunks/DLT1iIlz.js +2 -0
  60. package/build/client/_app/immutable/chunks/pIrVVOVY.js +2 -0
  61. package/build/client/_app/immutable/entry/app.0DERehLW.js +3 -0
  62. package/build/client/_app/immutable/entry/payload.DSmR2FwN.js +2 -0
  63. package/build/client/_app/immutable/entry/start.B7srFiqh.js +3 -0
  64. package/build/client/_app/immutable/nodes/0.aD9vJoxR.js +2 -0
  65. package/build/client/_app/immutable/nodes/1.Br4FL91i.js +2 -0
  66. package/build/client/_app/immutable/nodes/2.vl6OYfu3.js +8 -0
  67. package/build/client/_app/immutable/nodes/3.VYqJOLAF.js +2 -0
  68. package/build/client/_app/immutable/nodes/4.jF9UVlFN.js +2 -0
  69. package/build/client/_app/version.json +1 -0
  70. package/build/client/apple-touch-icon.png +0 -0
  71. package/build/client/favicon.ico +0 -0
  72. package/build/client/favicon.svg +48 -0
  73. package/build/client/icon-192.png +0 -0
  74. package/build/client/icon-512.png +0 -0
  75. package/build/client/icon-maskable-512.png +0 -0
  76. package/build/client/icon.svg +44 -0
  77. package/build/client/manifest.webmanifest +15 -0
  78. package/build/error.svelte-JXZDY65F.js +51 -0
  79. package/build/handler.js +716 -0
  80. package/build/hooks.server-34IMHRKC.js +43 -0
  81. package/build/instance-NP3FJIWW.js +2967 -0
  82. package/client/client.mjs +28 -0
  83. package/client/hooks.mjs +7 -0
  84. package/client/register.mjs +5 -0
  85. package/dist/cli.js +62826 -0
  86. package/dist/port.js +36691 -0
  87. package/package.json +20 -1
  88. package/skills/agents/.claude-plugin/plugin.json +5 -0
  89. package/skills/agents/hooks/hooks.json +1 -0
  90. package/skills/agents/hooks/register.ts +57 -0
  91. package/skills/agents/skills/bus-work/SKILL.md +66 -0
  92. package/skills/agents/skills/plan/SKILL.md +98 -0
  93. package/skills/console/.claude-plugin/plugin.json +5 -0
  94. package/skills/console/hooks/hooks.json +1 -0
  95. package/skills/console/hooks/register.ts +10 -0
  96. package/skills/console/skills/bus/SKILL.md +61 -0
  97. package/skills/default/.claude-plugin/plugin.json +5 -0
  98. package/skills/default/skills/git-workflow/SKILL.md +294 -0
  99. package/skills/default/skills/git-workflow/mise-tasks/_lib.sh +107 -0
  100. package/skills/default/skills/git-workflow/mise-tasks/clone +36 -0
  101. package/skills/default/skills/git-workflow/mise-tasks/repo-list +8 -0
  102. package/skills/default/skills/git-workflow/mise-tasks/unpushed +26 -0
  103. package/skills/default/skills/git-workflow/mise-tasks/worktree-add +60 -0
  104. package/skills/default/skills/github/SKILL.md +208 -0
  105. package/skills/default/skills/github/scripts/gh-org +196 -0
  106. package/skills/default/skills/plan-page/SKILL.md +300 -0
  107. package/skills/default/skills/plan-page/assets/index.html +854 -0
  108. package/skills/default/skills/plan-page/scripts/inline +46 -0
  109. package/skills/default/skills/plan-page/scripts/stage +26 -0
  110. package/skills/default/skills/secrets/SKILL.md +134 -0
  111. package/skills/default/skills/secrets/scripts/secrets-check +87 -0
  112. package/skills/default/skills/writing-style/SKILL.md +45 -0
  113. package/skills/extra/.claude-plugin/plugin.json +5 -0
  114. package/skills/extra/skills/artifacts/SKILL.md +52 -0
  115. package/skills/extra/skills/github-actions/SKILL.md +78 -0
  116. package/skills/extra/skills/github-actions/scan +32 -0
  117. package/skills/extra/skills/markdown-review/SKILL.md +70 -0
  118. package/skills/extra/skills/markdown-review/assets/index.html +201 -0
  119. package/skills/extra/skills/markdown-review/scripts/stage +36 -0
  120. package/skills/extra/skills/mise-usage/SKILL.md +155 -0
  121. package/skills/extra/skills/plugin-authoring/SKILL.md +317 -0
  122. package/skills/extra/skills/project-conventions/SKILL.md +64 -0
  123. package/skills/extra/skills/questions/SKILL.md +156 -0
  124. package/skills/extra/skills/questions/assets/index.html +376 -0
  125. package/skills/extra/skills/questions/scripts/stage +26 -0
  126. package/skills/extra/skills/serve/SKILL.md +165 -0
  127. package/skills/extra/skills/serve/scripts/serve +268 -0
  128. package/skills/extra/skills/serve/scripts/server.py +345 -0
  129. package/skills/extra/skills/skill-dependencies/SKILL.md +65 -0
  130. package/skills/extra/skills/skill-maintenance/SKILL.md +101 -0
  131. package/skills/extra/skills/ticketing/SKILL.md +125 -0
@@ -0,0 +1,1091 @@
1
+ import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
+ import {
3
+ DOC_SANDBOX
4
+ } from "./chunk-MC5AGLMY.js";
5
+ import {
6
+ Button,
7
+ Icon,
8
+ Pending,
9
+ buttonState,
10
+ pendingContext,
11
+ providePending
12
+ } from "./chunk-BJTJS3XY.js";
13
+ import {
14
+ external_exports
15
+ } from "./chunk-NCZ77J5E.js";
16
+ import {
17
+ attr,
18
+ attr_class,
19
+ attr_style,
20
+ attributes,
21
+ bind_props,
22
+ clsx,
23
+ derived,
24
+ element,
25
+ ensure_array_like,
26
+ escape_html,
27
+ fallback,
28
+ getContext,
29
+ props_id,
30
+ setContext,
31
+ spread_props,
32
+ stringify,
33
+ to_array
34
+ } from "./chunk-KAYW2W7H.js";
35
+
36
+ // build/server/chunks/DocDetail.js
37
+ var favicon_default = "data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='1024'%20height='1024'%20viewBox='-50%20-50%201354%201354'%20role='img'%20aria-labelledby='title%20desc'%3e%3ctitle%20id='title'%3eCoordinator%20mark%3c/title%3e%3cdesc%20id='desc'%3eCream%20C-shaped%20gear%20surrounding%20four%20robot%20agents,%20connected%20with%20orange%20arcs%20and%20spokes.%20Transparent%20background.%3c/desc%3e%3cstyle%3e%20/*%20Change%20fill%20to%20any%20color%20for%20a%20solid%20background.%20No%20checkerboard%20is%20drawn.%20*/%20.background%20{fill:none;}%20.gear%20{fill:%23FFF6E9;stroke:%23091216;stroke-width:64;paint-order:stroke;stroke-linejoin:round;stroke-linecap:round;}%20.disc%20{fill:%23091216;}%20.connections%20{fill:none;stroke:%23FF8A00;stroke-width:49;}%20.spokes%20{fill:none;stroke:%23FF8A00;stroke-width:35;}%20.robot-shell%20{fill:%23FFF6E9;stroke:%23091216;stroke-width:24;}%20.robot-face%20{fill:%23091216;}%20.eyes%20{fill:%23FFFAF2;}%20.antenna-stem%20{stroke:%23FFF6E9;stroke-width:25;}%20.antenna-tip%20{fill:%23FFF6E9;stroke:%23091216;stroke-width:20;}%20[id^=robot-]%20{display:none;}%20.connections%20{stroke-width:110;}%20.spokes%20{stroke-width:90;}%20.gear%20{stroke-width:100;}%20%3c/style%3e%3cg%20id='background'%20data-name='Background,%20transparent;%20set%20its%20CSS%20fill%20for%20a%20solid%20one'%3e%3crect%20class='background'%20x='-16'%20y='-16'%20width='1286'%20height='1286'/%3e%3c/g%3e%3cg%20id='c-gear'%20data-name='C-shaped%20cream%20gear'%3e%3cpath%20class='gear'%20d='M971%20424%20L1104%20323%20Q1133%20299%201113%20267%20L990%20144%20Q963%20119%20934%20137%20L867%20169%20L782%20134%20L751%2051%20Q742%2027%20714%2027%20H582%20Q551%2027%20540%2053%20L506%20134%20L416%20173%20L351%20138%20Q325%20123%20302%20143%20L201%20244%20Q182%20264%20193%20290%20L220%20340%20L179%20426%20L96%20446%20Q73%20452%2066%20483%20L49%20580%20Q44%20607%2067%20623%20L119%20659%20L131%20753%20L85%20801%20Q65%20823%2080%20850%20L126%20939%20Q138%20964%20166%20959%20L239%20947%20L297%201008%20L285%201085%20Q280%201114%20303%201131%20L393%201182%20Q415%201195%20439%201177%20L492%201127%20L575%201147%20L604%201207%20Q614%201228%20641%201228%20H730%20Q755%201228%20766%201205%20L797%201142%20Q966%201130%201113%20986%20Q1139%20958%201117%20935%20L991%20856%20L908%20887%20A378%20378%200%201%201%20942%20418%20Z'/%3e%3c/g%3e%3cg%20id='central-disc'%20data-name='Dark%20central%20disc'%3e%3ccircle%20class='disc'%20cx='630'%20cy='631'%20r='367'/%3e%3c/g%3e%3cg%20id='inside'%20data-name='Everything%20inside%20the%20C,%20scaled%20to%20its%20opening'%20transform='translate(630%20631)%20scale(0.9)%20translate(-630%20-631)'%3e%3cg%20id='orange-orbit'%20data-name='Orange%20connecting%20arcs'%20class='connections'%3e%3ccircle%20cx='630'%20cy='621'%20r='329'/%3e%3c/g%3e%3cg%20id='orange-spokes'%20data-name='Orange%20connecting%20spokes'%20class='spokes'%3e%3cpath%20d='M632%20391V845%20M352%20622H919'/%3e%3c/g%3e%3cg%20id='robot-top'%20data-name='Robot%20top'%20transform='translate(634%20335)'%3e%3cg%20id='antenna-top'%20data-name='Antenna'%3e%3ccircle%20class='antenna-tip'%20cx='0'%20cy='-144'%20r='39'/%3e%3cpath%20class='antenna-stem'%20d='M0%20-144V-67'/%3e%3c/g%3e%3crect%20class='robot-shell'%20x='-130'%20y='-97'%20width='260'%20height='196'%20rx='86'/%3e%3crect%20class='robot-face'%20x='-89'%20y='-44'%20width='178'%20height='99'%20rx='40'/%3e%3cg%20class='eyes'%20data-name='Eyes'%3e%3ccircle%20cx='-42'%20cy='4'%20r='18.5'/%3e%3ccircle%20cx='42'%20cy='4'%20r='18.5'/%3e%3c/g%3e%3c/g%3e%3cg%20id='robot-left'%20data-name='Robot%20left'%20transform='translate(315%20625)'%3e%3cg%20id='antenna-left'%20data-name='Antenna'%3e%3ccircle%20class='antenna-tip'%20cx='0'%20cy='-144'%20r='39'/%3e%3cpath%20class='antenna-stem'%20d='M0%20-144V-67'/%3e%3c/g%3e%3crect%20class='robot-shell'%20x='-130'%20y='-97'%20width='260'%20height='196'%20rx='86'/%3e%3crect%20class='robot-face'%20x='-89'%20y='-44'%20width='178'%20height='99'%20rx='40'/%3e%3cg%20class='eyes'%20data-name='Eyes'%3e%3ccircle%20cx='-42'%20cy='4'%20r='18.5'/%3e%3ccircle%20cx='42'%20cy='4'%20r='18.5'/%3e%3c/g%3e%3c/g%3e%3cg%20id='robot-right'%20data-name='Robot%20right'%20transform='translate(940%20625)'%3e%3cg%20id='antenna-right'%20data-name='Antenna'%3e%3ccircle%20class='antenna-tip'%20cx='0'%20cy='-144'%20r='39'/%3e%3cpath%20class='antenna-stem'%20d='M0%20-144V-67'/%3e%3c/g%3e%3crect%20class='robot-shell'%20x='-130'%20y='-97'%20width='260'%20height='196'%20rx='86'/%3e%3crect%20class='robot-face'%20x='-89'%20y='-44'%20width='178'%20height='99'%20rx='40'/%3e%3cg%20class='eyes'%20data-name='Eyes'%3e%3ccircle%20cx='-42'%20cy='4'%20r='18.5'/%3e%3ccircle%20cx='42'%20cy='4'%20r='18.5'/%3e%3c/g%3e%3c/g%3e%3cg%20id='robot-bottom'%20data-name='Robot%20bottom'%20transform='translate(633%20957)'%3e%3cg%20id='antenna-bottom'%20data-name='Antenna'%3e%3ccircle%20class='antenna-tip'%20cx='0'%20cy='-144'%20r='39'/%3e%3cpath%20class='antenna-stem'%20d='M0%20-144V-67'/%3e%3c/g%3e%3crect%20class='robot-shell'%20x='-130'%20y='-97'%20width='260'%20height='196'%20rx='86'/%3e%3crect%20class='robot-face'%20x='-89'%20y='-44'%20width='178'%20height='99'%20rx='40'/%3e%3cg%20class='eyes'%20data-name='Eyes'%3e%3ccircle%20cx='-42'%20cy='4'%20r='18.5'/%3e%3ccircle%20cx='42'%20cy='4'%20r='18.5'/%3e%3c/g%3e%3c/g%3e%3c/g%3e%3c/svg%3e";
38
+ function IconButton($$renderer, $$props) {
39
+ $$renderer.component(($$renderer2) => {
40
+ let { icon, label, type = "button", cancel = false, error = "", onclick, class: className, $$slots, $$events, ...rest } = $$props;
41
+ const own = new Pending({ name: "An IconButton onclick" });
42
+ const form = pendingContext();
43
+ const state = derived(() => buttonState({
44
+ own,
45
+ form,
46
+ submit: type === "submit",
47
+ cancel
48
+ }));
49
+ $$renderer2.push(`<button${attributes({
50
+ type,
51
+ class: clsx(["sd-iconbtn", className]),
52
+ "aria-label": label,
53
+ title: label,
54
+ "aria-disabled": state().blocked ? "true" : void 0,
55
+ "aria-busy": state().spinning ? "true" : void 0,
56
+ ...rest
57
+ })}>`);
58
+ if (state().spinning) $$renderer2.push(`<!--[0--><span class="sd-spinner" aria-hidden="true"></span>`);
59
+ else {
60
+ $$renderer2.push("<!--[-1-->");
61
+ Icon($$renderer2, { name: icon });
62
+ }
63
+ $$renderer2.push(`<!--]--></button>`);
64
+ bind_props($$props, { error });
65
+ });
66
+ }
67
+ function Dialog$1($$renderer, $$props) {
68
+ $$renderer.component(($$renderer2) => {
69
+ const uid = props_id($$renderer2);
70
+ let { open = false, title, description, icon, size = "md", onclose, onsubmit, abortable = false, children, footer } = $$props;
71
+ const wait = onsubmit ? providePending(new Pending({
72
+ name: "A Dialog onsubmit",
73
+ abortable
74
+ })) : void 0;
75
+ function close() {
76
+ if (wait?.busy) {
77
+ if (!wait.abortable) return;
78
+ wait.abort();
79
+ }
80
+ open = false;
81
+ onclose?.();
82
+ }
83
+ function content($$renderer3) {
84
+ if (children || wait?.error) {
85
+ $$renderer3.push(`<!--[0--><div class="sd-dialog-body">`);
86
+ children?.($$renderer3);
87
+ $$renderer3.push(`<!----> `);
88
+ if (wait?.error) $$renderer3.push(`<!--[0--><p class="sd-dialog-error" role="alert">${escape_html(wait.error)}</p>`);
89
+ else $$renderer3.push("<!--[-1-->");
90
+ $$renderer3.push(`<!--]--></div>`);
91
+ } else $$renderer3.push("<!--[-1-->");
92
+ $$renderer3.push(`<!--]--> `);
93
+ if (footer) {
94
+ $$renderer3.push(`<!--[0--><footer class="sd-dialog-foot">`);
95
+ footer($$renderer3);
96
+ $$renderer3.push(`<!----></footer>`);
97
+ } else $$renderer3.push("<!--[-1-->");
98
+ $$renderer3.push(`<!--]-->`);
99
+ }
100
+ $$renderer2.push(`<dialog${attr_class(clsx([
101
+ "sd-dialog",
102
+ size === "sm" && "sd-dialog-sm",
103
+ size === "lg" && "sd-dialog-lg"
104
+ ]))}${attr("aria-labelledby", `sd-dialog-${uid}-title`)}${attr("aria-describedby", description ? `sd-dialog-${uid}-desc` : void 0)}><header class="sd-dialog-head">`);
105
+ if (icon) {
106
+ $$renderer2.push(`<!--[0--><span class="sd-dialog-icon">`);
107
+ Icon($$renderer2, { name: icon });
108
+ $$renderer2.push(`<!----></span>`);
109
+ } else $$renderer2.push("<!--[-1-->");
110
+ $$renderer2.push(`<!--]--> <div class="sd-dialog-titles"><h2 class="sd-dialog-title"${attr("id", `sd-dialog-${uid}-title`)}>${escape_html(title)}</h2> `);
111
+ if (description) $$renderer2.push(`<!--[0--><p class="sd-dialog-sub"${attr("id", `sd-dialog-${uid}-desc`)}>${escape_html(description)}</p>`);
112
+ else $$renderer2.push("<!--[-1-->");
113
+ $$renderer2.push(`<!--]--></div> `);
114
+ IconButton($$renderer2, {
115
+ icon: "x",
116
+ label: "Close",
117
+ cancel: true,
118
+ onclick: close
119
+ });
120
+ $$renderer2.push(`<!----></header> `);
121
+ if (wait) {
122
+ $$renderer2.push(`<!--[0--><form class="sd-dialog-form" novalidate="">`);
123
+ content($$renderer2);
124
+ $$renderer2.push(`<!----></form>`);
125
+ } else {
126
+ $$renderer2.push("<!--[-1-->");
127
+ content($$renderer2);
128
+ }
129
+ $$renderer2.push(`<!--]--></dialog>`);
130
+ bind_props($$props, { open });
131
+ });
132
+ }
133
+ var TYPE_BADGE = {
134
+ bug: {
135
+ label: "Bug",
136
+ tone: "warning"
137
+ },
138
+ feature: {
139
+ label: "Feature",
140
+ tone: "info"
141
+ },
142
+ task: {
143
+ label: "Task",
144
+ tone: "neutral"
145
+ },
146
+ chore: {
147
+ label: "Chore",
148
+ tone: "neutral"
149
+ }
150
+ };
151
+ var STATE_BADGE = {
152
+ open: {
153
+ label: "Open",
154
+ tone: "success"
155
+ },
156
+ held: {
157
+ label: "Held",
158
+ tone: "accent"
159
+ },
160
+ closed: {
161
+ label: "Closed",
162
+ tone: "neutral"
163
+ }
164
+ };
165
+ var WORK_PR_BADGE = {
166
+ open: {
167
+ label: "Opened",
168
+ tone: "info"
169
+ },
170
+ closed: {
171
+ label: "Closed",
172
+ tone: "neutral"
173
+ },
174
+ dry_run: {
175
+ label: "Dry run",
176
+ tone: "neutral"
177
+ }
178
+ };
179
+ var LANDING_BADGE = {
180
+ landing: {
181
+ label: "Landing",
182
+ tone: "info"
183
+ },
184
+ pr_open: {
185
+ label: "PR open",
186
+ tone: "info"
187
+ },
188
+ landed: {
189
+ label: "Landed",
190
+ tone: "success"
191
+ },
192
+ refused: {
193
+ label: "Refused",
194
+ tone: "warning"
195
+ },
196
+ failed: {
197
+ label: "Failed",
198
+ tone: "warning"
199
+ },
200
+ closed: {
201
+ label: "PR closed",
202
+ tone: "neutral"
203
+ },
204
+ dry_run: {
205
+ label: "Dry run",
206
+ tone: "neutral"
207
+ }
208
+ };
209
+ var ASK_LABEL = {
210
+ plan: "Plan to approve",
211
+ done: "Ready to land",
212
+ pr: "PR to open",
213
+ question: "Question"
214
+ };
215
+ function askedPlan(issues, ask) {
216
+ if (ask?.kind !== "plan" || !ask.about) return null;
217
+ const issue = issues.find((i) => i.address === ask.about);
218
+ const plan = issue && (issue.plans.findLast((p) => !p.approved_at) ?? issue.plans.at(-1));
219
+ return issue && plan ? {
220
+ issue,
221
+ plan
222
+ } : null;
223
+ }
224
+ function blockerBadge(i) {
225
+ if (!i) return {
226
+ label: "Unknown",
227
+ tone: "danger"
228
+ };
229
+ if (i.landed) return {
230
+ label: "Landed",
231
+ tone: "success"
232
+ };
233
+ if (i.state === "closed") return {
234
+ label: "Closed, not landed",
235
+ tone: "danger"
236
+ };
237
+ return {
238
+ label: STATE_BADGE[i.state].label,
239
+ tone: i.state === "held" ? "accent" : "warning"
240
+ };
241
+ }
242
+ var leadOfIn = (st) => (slot) => {
243
+ const id = st.slots[slot];
244
+ return id === void 0 ? void 0 : st.sessions[id]?.lead ?? null;
245
+ };
246
+ var waitersOf = (issues, address) => issues.filter((i) => i.blocked_by.includes(address));
247
+ var waitingOn = (issues, i) => i.blocked_by.filter((b) => !issues.find((x) => x.address === b)?.landed);
248
+ function checkoutNotices(repos) {
249
+ return repos.filter((r) => r.checkout).map((r) => ({
250
+ kind: "checkout",
251
+ key: `checkout:${r.repo}`,
252
+ tone: "warning",
253
+ href: repoHash(r.repo),
254
+ title: `${r.repo} checkout behind`,
255
+ text: `Its ${r.default_branch} at ${r.checkout.at} is ${r.checkout.behind} behind origin and was not fast-forwarded: ${r.checkout.why}. ${r.checkout.fix} The bus retries every minute.`
256
+ }));
257
+ }
258
+ function recordNotices(problems) {
259
+ return problems.map((p) => ({
260
+ kind: "record",
261
+ key: `record:${p.file}`,
262
+ tone: "warning",
263
+ href: "#skills",
264
+ title: `${p.file} skipped`,
265
+ text: p.file.startsWith(".coord/") ? `It could not be read: ${p.detail}. Fix the file, then restart the server to read it.` : `${p.detail}. Fix it in the Repo: its Profiles are read again each time its checkout moves.`
266
+ }));
267
+ }
268
+ function groupOf(groupings, i) {
269
+ const g = groupings[i.repo]?.groups.find((x) => x.issues.includes(i.address));
270
+ return g ? {
271
+ with: g.issues.filter((a) => a !== i.address),
272
+ why: g.why
273
+ } : null;
274
+ }
275
+ var docHash = (id) => `#d=${encodeURIComponent(id)}`;
276
+ var stateOf = (s) => s.state || "unknown";
277
+ var when = (t) => t ? new Date(t).toLocaleTimeString([], {
278
+ hour: "numeric",
279
+ minute: "2-digit"
280
+ }) : "";
281
+ var repoOf = (s) => s.repo || "no repo";
282
+ var issueHash = (i) => "#i=" + encodeURIComponent(i);
283
+ var repoHash = (r) => "#r=" + encodeURIComponent(r);
284
+ var changeHash = (r, id) => repoHash(r) + "~" + id;
285
+ var repoGithubUrl = (r) => `https://github.com/${r}`;
286
+ var repoSettingsHash = (r) => "#rs=" + encodeURIComponent(r);
287
+ var repoSecretsHash = (r) => "#rk=" + encodeURIComponent(r);
288
+ var slotSecretsHash = (slot) => "#ss=" + encodeURIComponent(slot);
289
+ var sessionHash = (id) => "#s=" + encodeURIComponent(id);
290
+ var waiting = (s) => !s.ended && s.state === "starting" && Date.now() - new Date(s.started).getTime() > 2e4;
291
+ function ago(t, at = Date.now()) {
292
+ if (!t) return "";
293
+ const seconds = Math.max(0, (at - new Date(t).getTime()) / 1e3);
294
+ for (const [unit, size] of [
295
+ ["year", 31536e3],
296
+ ["month", 2592e3],
297
+ ["week", 604800],
298
+ ["day", 86400],
299
+ ["hour", 3600],
300
+ ["minute", 60]
301
+ ]) {
302
+ const n = Math.floor(seconds / size);
303
+ if (n >= 1) return `${n} ${unit}${n === 1 ? "" : "s"} ago`;
304
+ }
305
+ return "just now";
306
+ }
307
+ function hashOf(hash2, kind) {
308
+ const match = hash2.match(new RegExp("^#" + kind + "=(.+)$"));
309
+ return match ? decodeURIComponent(match[1]) : "";
310
+ }
311
+ var KEY = Symbol("page");
312
+ var POLL_MS = 2e3;
313
+ var Page = class {
314
+ csrf;
315
+ st = null;
316
+ hash = "";
317
+ note = "";
318
+ navOpen = false;
319
+ /** Whether the last poll reached the server. */
320
+ live = false;
321
+ /** Why Herdr did not switch to the pane the user asked for, shown in a warning dialog until they close it. */
322
+ switchWarning = "";
323
+ /** The dialog asked for, and what it is for: a slot, a Session, or an issue. n changes on every ask, so asking again reopens it;
324
+ * shown is called once it is open, or once it cannot be. */
325
+ dialog = null;
326
+ last = "";
327
+ asked = 0;
328
+ /** The held work the note is about, cleared with the note once the throttle no longer holds it. */
329
+ heldNote = null;
330
+ /** Ask for a dialog; resolves once it is open, so a button that opens one that reads first, such as Clean up, waits on it. */
331
+ open(kind, arg = "") {
332
+ return new Promise((shown) => this.dialog = {
333
+ kind,
334
+ arg,
335
+ n: ++this.asked,
336
+ shown
337
+ });
338
+ }
339
+ constructor(csrf) {
340
+ this.csrf = csrf;
341
+ }
342
+ get selected() {
343
+ return hashOf(this.hash, "s");
344
+ }
345
+ get selectedIssue() {
346
+ return hashOf(this.hash, "i");
347
+ }
348
+ get selectedRepo() {
349
+ return hashOf(this.hash, "r").split("~")[0];
350
+ }
351
+ /** The Change Summary opened on the repo's page, from a slot's link to its landing; 0 when none. */
352
+ get selectedChange() {
353
+ return Number(hashOf(this.hash, "r").split("~")[1] ?? 0) || 0;
354
+ }
355
+ /** The repo whose Settings view is open. */
356
+ get selectedRepoSettings() {
357
+ return hashOf(this.hash, "rs");
358
+ }
359
+ /** The repo whose Secrets view is open. */
360
+ get selectedRepoSecrets() {
361
+ return hashOf(this.hash, "rk");
362
+ }
363
+ /** The slot whose Secrets view is open. */
364
+ get selectedSlotSecrets() {
365
+ return hashOf(this.hash, "ss");
366
+ }
367
+ /** The profile, skill group, or instruction open in its editor, as kind:name. */
368
+ /** The document open in the Documents view. */
369
+ get selectedDoc() {
370
+ return hashOf(this.hash, "d");
371
+ }
372
+ get selectedPart() {
373
+ return hashOf(this.hash, "sk");
374
+ }
375
+ go(hash2) {
376
+ location.hash = hash2;
377
+ }
378
+ async poll() {
379
+ try {
380
+ const r = await fetch("state.json", { cache: "no-store" });
381
+ if (r.status === 401) {
382
+ location.href = "pair";
383
+ return;
384
+ }
385
+ const text = await r.text();
386
+ this.live = r.ok;
387
+ if (text !== this.last) {
388
+ this.last = text;
389
+ this.st = JSON.parse(text);
390
+ }
391
+ this.dropHeldNote();
392
+ } catch {
393
+ this.live = false;
394
+ }
395
+ }
396
+ /** Say a start is held, until the throttle runs it or another note replaces this one. */
397
+ held(id, text) {
398
+ this.note = text;
399
+ this.heldNote = {
400
+ id,
401
+ text
402
+ };
403
+ this.dropHeldNote();
404
+ }
405
+ dropHeldNote() {
406
+ const h = this.heldNote;
407
+ if (!h || !this.st) return;
408
+ if (this.note !== h.text) this.heldNote = null;
409
+ else if (!this.st.throttle.held.some((x) => x.id === h.id)) {
410
+ this.note = "";
411
+ this.heldNote = null;
412
+ }
413
+ }
414
+ start() {
415
+ const onHash = () => this.hash = location.hash;
416
+ onHash();
417
+ window.addEventListener("hashchange", onHash);
418
+ this.poll();
419
+ const timer = setInterval(() => void this.poll(), POLL_MS);
420
+ return () => {
421
+ clearInterval(timer);
422
+ window.removeEventListener("hashchange", onHash);
423
+ };
424
+ }
425
+ async post(path, body) {
426
+ return (await fetch(path, {
427
+ method: "POST",
428
+ headers: {
429
+ "Content-Type": "application/json",
430
+ "X-CSRF": this.csrf
431
+ },
432
+ body: JSON.stringify(body)
433
+ })).json();
434
+ }
435
+ /** Switch Herdr to the Session's pane; the page shows the Session either way, and a warning says why when Herdr did not switch.
436
+ * An ended one opens Clean up instead, the first time only. */
437
+ async focus(session) {
438
+ const out = await this.post("focus", { session }).catch(() => ({ error: "the server did not answer" }));
439
+ this.switchWarning = out.error || "";
440
+ if (out.cleanup) await this.open("cleanup", session);
441
+ }
442
+ /** Open a shell on the repo's checkout in Herdr and switch to it; the note under the header says why when Herdr refuses. */
443
+ async terminal(repo) {
444
+ const out = await this.post("terminal", { repo }).catch(() => ({ error: "the server did not answer" }));
445
+ this.note = out.error || "";
446
+ }
447
+ /** Send a Message as user; the note under the header says why when it is refused. */
448
+ async act(body) {
449
+ const out = await this.post("act", body);
450
+ this.note = out.error || "";
451
+ await this.poll();
452
+ return out;
453
+ }
454
+ };
455
+ function providePage(page) {
456
+ return setContext(KEY, page);
457
+ }
458
+ function usePage() {
459
+ return getContext(KEY);
460
+ }
461
+ var defaultAttributes = {
462
+ xmlns: "http://www.w3.org/2000/svg",
463
+ width: 24,
464
+ height: 24,
465
+ viewBox: "0 0 24 24",
466
+ fill: "none",
467
+ stroke: "currentColor",
468
+ "stroke-width": 2,
469
+ "stroke-linecap": "round",
470
+ "stroke-linejoin": "round"
471
+ };
472
+ var mergeClasses = (...classes) => classes.filter((className, index, array) => {
473
+ return Boolean(className) && className.trim() !== "" && array.indexOf(className) === index;
474
+ }).join(" ").trim();
475
+ function isDefined(value) {
476
+ return value !== null && value !== void 0;
477
+ }
478
+ function buildLucideIconNode(icon, params = {}) {
479
+ const attributeNames = params.attributeNames ?? {};
480
+ const getAttributeName = (attributeName) => attributeNames[attributeName] ?? attributeName;
481
+ const viewBoxWidth = icon.size ?? icon.width ?? defaultAttributes["width"];
482
+ const viewBoxHeight = icon.size ?? icon.height ?? defaultAttributes["height"];
483
+ const aliasClassNames = icon.aliases?.filter((alias) => typeof alias === "string" && alias.trim() !== "").map((alias) => `lucide-${alias}`) ?? [];
484
+ const iconClassNames = [...icon.name ? [`lucide-${icon.name}`] : [], ...aliasClassNames];
485
+ const classNamesFromClassName = params.className?.split(" ").filter(Boolean) ?? [];
486
+ const className = params.includeDefaultClasses === false ? mergeClasses(...classNamesFromClassName) : mergeClasses("lucide", ...iconClassNames, ...classNamesFromClassName);
487
+ const calculatedStrokeWidth = params.absoluteStrokeWidth ? Number(params.strokeWidth ?? defaultAttributes["stroke-width"]) * Number(icon.size ?? icon.width ?? defaultAttributes["width"]) / Number(params.size ?? params.width ?? defaultAttributes["width"]) : params.strokeWidth ?? defaultAttributes["stroke-width"];
488
+ return [
489
+ "svg",
490
+ {
491
+ ...Object.entries(defaultAttributes).reduce((attrs, [attrName, value]) => {
492
+ attrs[getAttributeName(attrName)] = value;
493
+ return attrs;
494
+ }, {}),
495
+ ..."color" in params && params.color && { [getAttributeName("stroke")]: params.color },
496
+ ..."size" in params && isDefined(params.size) && {
497
+ [getAttributeName("width")]: params.size,
498
+ [getAttributeName("height")]: params.size
499
+ },
500
+ ..."width" in params && isDefined(params.width) && { [getAttributeName("width")]: params.width },
501
+ ..."height" in params && isDefined(params.height) && { [getAttributeName("height")]: params.height },
502
+ [getAttributeName("stroke-width")]: calculatedStrokeWidth,
503
+ ...className && { [getAttributeName("class")]: className },
504
+ [getAttributeName("viewBox")]: `0 0 ${viewBoxWidth} ${viewBoxHeight}`,
505
+ ...params.hasA11yProp === false ? { [getAttributeName("aria-hidden")]: "true" } : {},
506
+ ..."attributes" in params && params.attributes
507
+ },
508
+ icon.node.map((child) => {
509
+ const [name, attrs, children] = child;
510
+ const nextAttrs = params.nonScalingStroke ? {
511
+ [getAttributeName("vector-effect")]: "non-scaling-stroke",
512
+ ...attrs
513
+ } : attrs;
514
+ return children ? [
515
+ name,
516
+ nextAttrs,
517
+ children
518
+ ] : [name, nextAttrs];
519
+ })
520
+ ];
521
+ }
522
+ var hasA11yProp = (props) => {
523
+ for (const prop in props) if (prop.startsWith("aria-") || prop === "role" || prop === "title") return true;
524
+ return false;
525
+ };
526
+ var LucideContext = Symbol("lucide-context");
527
+ var getLucideContext = () => getContext(LucideContext);
528
+ function Icon2($$renderer, $$props) {
529
+ $$renderer.component(($$renderer2) => {
530
+ const globalProps = getLucideContext() ?? {};
531
+ const { color = globalProps.color ?? "currentColor", size = globalProps.size ?? 24, width = size, height = size, strokeWidth = globalProps.strokeWidth ?? 2, absoluteStrokeWidth = globalProps.absoluteStrokeWidth ?? false, nonScalingStroke = globalProps.nonScalingStroke ?? false, iconNode = [], icon = {
532
+ node: iconNode,
533
+ aliases: [],
534
+ size: 24
535
+ }, class: propsClass, children, $$slots, $$events, ...props } = $$props;
536
+ const hasAccessibleProp = derived(() => Boolean(children) || hasA11yProp(props));
537
+ const $$d = derived(() => buildLucideIconNode(icon, {
538
+ color,
539
+ width,
540
+ height,
541
+ strokeWidth,
542
+ absoluteStrokeWidth,
543
+ nonScalingStroke,
544
+ className: mergeClasses("lucide-icon", globalProps.class),
545
+ hasA11yProp: hasAccessibleProp(),
546
+ attributes: props
547
+ })), $$derived_array = derived(() => to_array($$d(), 3)), svgAttributes = derived(() => $$derived_array()[1]), builtIconNode = derived(() => fallback($$derived_array()[2], () => [], true));
548
+ const iconAttributes = derived(() => ({
549
+ ...svgAttributes(),
550
+ class: [...svgAttributes().class.split(" "), propsClass]
551
+ }));
552
+ $$renderer2.push(`<svg${attributes({ ...iconAttributes() }, void 0, void 0, void 0, 3)}><!--[-->`);
553
+ const each_array = ensure_array_like(builtIconNode());
554
+ for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
555
+ let [tag, attrs] = each_array[$$index];
556
+ element($$renderer2, tag, () => {
557
+ $$renderer2.push(`${attributes({ ...attrs }, void 0, void 0, void 0, 3)}`);
558
+ });
559
+ }
560
+ $$renderer2.push(`<!--]-->`);
561
+ children?.($$renderer2);
562
+ $$renderer2.push(`<!----></svg>`);
563
+ });
564
+ }
565
+ function Circle_check($$renderer, $$props) {
566
+ let { $$slots, $$events, ...props } = $$props;
567
+ Icon2($$renderer, spread_props([props, { icon: {
568
+ "name": "circle-check",
569
+ "size": 24,
570
+ "node": [["circle", {
571
+ "cx": "12",
572
+ "cy": "12",
573
+ "r": "10"
574
+ }], ["path", { "d": "m16 9-5.5 5.5L8 12" }]],
575
+ "aliases": ["check-circle-2"]
576
+ } }]));
577
+ }
578
+ function External_link($$renderer, $$props) {
579
+ let { $$slots, $$events, ...props } = $$props;
580
+ Icon2($$renderer, spread_props([props, { icon: {
581
+ "name": "external-link",
582
+ "size": 24,
583
+ "node": [
584
+ ["path", { "d": "M15 3h6v6" }],
585
+ ["path", { "d": "M10 14 21 3" }],
586
+ ["path", { "d": "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }]
587
+ ]
588
+ } }]));
589
+ }
590
+ function SlotLink($$renderer, $$props) {
591
+ $$renderer.component(($$renderer2) => {
592
+ let { id = null, slot = null } = $$props;
593
+ const page = usePage();
594
+ const target = derived(() => id ?? (slot ? page.st.slots[slot] : null) ?? null);
595
+ const s = derived(() => target() ? page.st.sessions[target()] : null);
596
+ if (s()) $$renderer2.push(`<!--[0--><a${attr("href", sessionHash(s().id))}>${escape_html(s().slot || s().track)}</a>`);
597
+ else $$renderer2.push(`<!--[-1-->${escape_html(id ?? slot)}`);
598
+ $$renderer2.push(`<!--]-->`);
599
+ });
600
+ }
601
+ var UserColor = external_exports.string().regex(/^#[0-9a-fA-F]{6}$/, "Choose a color.");
602
+ var toLinear = (c) => c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
603
+ var fromLinear = (c) => c <= 31308e-7 ? 12.92 * c : 1.055 * c ** (1 / 2.4) - 0.055;
604
+ var hexToLinear = (hex) => [
605
+ 1,
606
+ 3,
607
+ 5
608
+ ].map((i) => toLinear(parseInt(hex.slice(i, i + 2), 16) / 255));
609
+ function hexToOklch(hex) {
610
+ const [r, g, b] = hexToLinear(hex);
611
+ const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);
612
+ const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);
613
+ const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);
614
+ const L = 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s;
615
+ const A = 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s;
616
+ const B = 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s;
617
+ return {
618
+ L,
619
+ C: Math.hypot(A, B),
620
+ h: (Math.atan2(B, A) * 180 / Math.PI + 360) % 360
621
+ };
622
+ }
623
+ function oklchToLinear(L, C, h) {
624
+ const a = C * Math.cos(h * Math.PI / 180);
625
+ const b = C * Math.sin(h * Math.PI / 180);
626
+ const l = (L + 0.3963377774 * a + 0.2158037573 * b) ** 3;
627
+ const m = (L - 0.1055613458 * a - 0.0638541728 * b) ** 3;
628
+ const s = (L - 0.0894841775 * a - 1.291485548 * b) ** 3;
629
+ return [
630
+ 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,
631
+ -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,
632
+ -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s
633
+ ];
634
+ }
635
+ var inGamut = (rgb) => rgb.every((c) => c >= -1e-4 && c <= 1.0001);
636
+ var toHex = (rgb) => "#" + rgb.map((c) => Math.round(fromLinear(Math.min(1, Math.max(0, c))) * 255).toString(16).padStart(2, "0")).join("");
637
+ var luminance = ([r, g, b]) => 0.2126 * r + 0.7152 * g + 0.0722 * b;
638
+ var contrast = (x, y) => (Math.max(x, y) + 0.05) / (Math.min(x, y) + 0.05);
639
+ var RANGE = {
640
+ dark: {
641
+ L: [0.7, 0.88],
642
+ maxC: 0.16,
643
+ ground: "#161a20",
644
+ soft: {
645
+ L: 0.27,
646
+ C: 0.045,
647
+ step: -0.01,
648
+ stop: 0.16
649
+ }
650
+ },
651
+ light: {
652
+ L: [0.4, 0.53],
653
+ maxC: 0.16,
654
+ ground: "#f8f9fb",
655
+ soft: {
656
+ L: 0.955,
657
+ C: 0.03,
658
+ step: 5e-3,
659
+ stop: 0.995
660
+ }
661
+ }
662
+ };
663
+ function fitGamut(L, C, h) {
664
+ for (let c = C; c > 0; c -= 5e-3) {
665
+ const rgb = oklchToLinear(L, c, h);
666
+ if (inGamut(rgb)) return rgb;
667
+ }
668
+ return oklchToLinear(L, 0, h);
669
+ }
670
+ function fitTheme(theme, position, C, h) {
671
+ const r = RANGE[theme];
672
+ const ground = luminance(hexToLinear(r.ground));
673
+ let L = r.L[0] + position * (r.L[1] - r.L[0]);
674
+ let text = fitGamut(L, Math.min(C, r.maxC), h);
675
+ const away = theme === "dark" ? 0.01 : -0.01;
676
+ while (contrast(luminance(text), ground) < 4.5 && L > 0.05 && L < 0.98) {
677
+ L += away;
678
+ text = fitGamut(L, Math.min(C, r.maxC), h);
679
+ }
680
+ const y = luminance(text);
681
+ const s = r.soft;
682
+ let soft = fitGamut(s.L, Math.min(s.C, C), h);
683
+ for (let sl = s.L; theme === "dark" ? sl >= s.stop : sl <= s.stop; sl += s.step) {
684
+ soft = fitGamut(sl, Math.min(s.C, C), h);
685
+ if (contrast(y, luminance(soft)) >= 4.5) break;
686
+ }
687
+ return {
688
+ text: toHex(text),
689
+ soft: toHex(soft)
690
+ };
691
+ }
692
+ function fitColor(hex) {
693
+ const { L, C, h } = hexToOklch(UserColor.parse(hex));
694
+ const position = Math.min(1, Math.max(0, (L - 0.35) / 0.55));
695
+ return {
696
+ dark: fitTheme("dark", position, C, h),
697
+ light: fitTheme("light", 1 - position, C, h)
698
+ };
699
+ }
700
+ function hash(text) {
701
+ let h = 2166136261;
702
+ for (let i = 0; i < text.length; i++) {
703
+ h ^= text.charCodeAt(i);
704
+ h = Math.imul(h, 16777619);
705
+ }
706
+ return h >>> 0;
707
+ }
708
+ var LEVELS = [
709
+ 0.9,
710
+ 0.5,
711
+ 0.1
712
+ ];
713
+ var pick = (h, position) => toHex(fitGamut(0.45 + position * 0.4, 0.13, h));
714
+ var sequence = [];
715
+ var candidates;
716
+ function oklab(hex) {
717
+ const { L, C, h } = hexToOklch(hex);
718
+ return [
719
+ L,
720
+ C * Math.cos(h * Math.PI / 180),
721
+ C * Math.sin(h * Math.PI / 180)
722
+ ];
723
+ }
724
+ function nthColor(n) {
725
+ if (!candidates) {
726
+ candidates = [];
727
+ for (let h = 0; h < 360; h += 4) for (const level of LEVELS) {
728
+ const hex = pick(h, level);
729
+ const f = fitColor(hex);
730
+ candidates.push({
731
+ h,
732
+ level: LEVELS.indexOf(level),
733
+ hex,
734
+ dark: oklab(f.dark.text),
735
+ light: oklab(f.light.text)
736
+ });
737
+ }
738
+ sequence.push(candidates.reduce((a, c) => Math.abs(c.h - 256) + c.level < Math.abs(a.h - 256) + a.level ? c : a));
739
+ }
740
+ while (sequence.length <= n) {
741
+ let best = null;
742
+ let bestGap = -1;
743
+ for (const c of candidates) {
744
+ let gap = Infinity;
745
+ for (const s of sequence) gap = Math.min(gap, Math.hypot(c.dark[0] - s.dark[0], c.dark[1] - s.dark[1], c.dark[2] - s.dark[2]), Math.hypot(c.light[0] - s.light[0], c.light[1] - s.light[1], c.light[2] - s.light[2]));
746
+ if (gap > bestGap) [best, bestGap] = [c, gap];
747
+ }
748
+ sequence.push(best);
749
+ }
750
+ return sequence[n].hex;
751
+ }
752
+ function seedColor(seed) {
753
+ if (typeof seed === "number") return nthColor(Math.max(0, Math.trunc(seed) - 1));
754
+ const x = hash(String(seed).trim().toLowerCase());
755
+ return pick(x % 360, LEVELS[Math.floor(x / 360) % LEVELS.length]);
756
+ }
757
+ function colorStyle({ color, seed }) {
758
+ const hex = color && UserColor.safeParse(color).success ? color : seed != null && seed !== "" ? seedColor(seed) : null;
759
+ if (!hex) return "";
760
+ const f = fitColor(hex);
761
+ return `--cat-d: ${f.dark.text}; --cat-soft-d: ${f.dark.soft}; --cat-l: ${f.light.text}; --cat-soft-l: ${f.light.soft};`;
762
+ }
763
+ function Badge($$renderer, $$props) {
764
+ $$renderer.component(($$renderer2) => {
765
+ let { tone = "neutral", color, seed, fill = false, dot = false, children } = $$props;
766
+ const style = derived(() => colorStyle({
767
+ color,
768
+ seed
769
+ }));
770
+ if (style()) {
771
+ $$renderer2.push(`<!--[0--><span${attr_class(clsx([
772
+ "sd-badge",
773
+ "sd-cat",
774
+ fill && "sd-badge-fill",
775
+ dot && "sd-badge-dot"
776
+ ]))}${attr_style(style())}>`);
777
+ children?.($$renderer2);
778
+ $$renderer2.push(`<!----></span>`);
779
+ } else {
780
+ $$renderer2.push(`<!--[-1--><span${attr_class(clsx([
781
+ "sd-badge",
782
+ tone !== "neutral" && `sd-badge-${tone}`,
783
+ dot && "sd-badge-dot"
784
+ ]))}>`);
785
+ children?.($$renderer2);
786
+ $$renderer2.push(`<!----></span>`);
787
+ }
788
+ $$renderer2.push(`<!--]-->`);
789
+ });
790
+ }
791
+ function Dialog($$renderer, $$props) {
792
+ $$renderer.component(($$renderer2) => {
793
+ let { id, form, title, sub, icon, action, danger = false, disabled = false, note = "", size = "md", open = false, onsubmit, children, extra } = $$props;
794
+ let $$settled = true;
795
+ let $$inner_renderer;
796
+ function $$render_inner($$renderer3) {
797
+ $$renderer3.push(`<div${attr("id", id)} class="dialog-host">`);
798
+ {
799
+ let footer2 = function($$renderer4) {
800
+ Button($$renderer4, {
801
+ variant: "quiet",
802
+ cancel: true,
803
+ "data-close": id,
804
+ onclick: () => open = false,
805
+ children: ($$renderer5) => {
806
+ $$renderer5.push(`<!---->Cancel`);
807
+ },
808
+ $$slots: { default: true }
809
+ });
810
+ $$renderer4.push(`<!----> `);
811
+ extra?.($$renderer4);
812
+ $$renderer4.push(`<!----> `);
813
+ Button($$renderer4, {
814
+ variant: danger ? "danger" : "primary",
815
+ type: "submit",
816
+ "data-form": form,
817
+ disabled,
818
+ children: ($$renderer5) => {
819
+ $$renderer5.push(`<!---->${escape_html(action)}`);
820
+ },
821
+ $$slots: { default: true }
822
+ });
823
+ $$renderer4.push(`<!---->`);
824
+ };
825
+ var footer = footer2;
826
+ Dialog$1($$renderer3, {
827
+ title,
828
+ description: sub,
829
+ icon,
830
+ size,
831
+ onsubmit: () => onsubmit(),
832
+ get open() {
833
+ return open;
834
+ },
835
+ set open($$value) {
836
+ open = $$value;
837
+ $$settled = false;
838
+ },
839
+ footer: footer2,
840
+ children: ($$renderer4) => {
841
+ $$renderer4.push(`<div${attr("id", form)} class="dialog-form">`);
842
+ children($$renderer4);
843
+ $$renderer4.push(`<!----> <div${attr("id", `${stringify(form)}-note`)} class="form-note" role="status">${escape_html(note)}</div></div>`);
844
+ },
845
+ $$slots: {
846
+ footer: true,
847
+ default: true
848
+ }
849
+ });
850
+ }
851
+ $$renderer3.push(`<!----></div>`);
852
+ }
853
+ do {
854
+ $$settled = true;
855
+ $$inner_renderer = $$renderer2.copy();
856
+ $$render_inner($$inner_renderer);
857
+ } while (!$$settled);
858
+ $$renderer2.subsume($$inner_renderer);
859
+ bind_props($$props, { open });
860
+ });
861
+ }
862
+ function DocDetail($$renderer, $$props) {
863
+ $$renderer.component(($$renderer2) => {
864
+ let { i, d, standalone = false } = $$props;
865
+ const page = usePage();
866
+ const p = derived(() => i.plans.find((p2) => p2.link === d.path));
867
+ let picked = null;
868
+ const shown = derived(() => picked !== null && d.versions.includes(picked) ? picked : d.version);
869
+ const src = derived(() => d.frame.replace(/\/\d+\/index\.html$/, `/${shown()}/index.html`));
870
+ const approvedOther = derived(() => !!p()?.approved_at && p().approved_version !== null && p().approved_version !== d.version);
871
+ let asked = null;
872
+ let askOpen = false;
873
+ let askNote = "";
874
+ derived(() => {
875
+ const st = page.st;
876
+ const holder = i.holder ? st.sessions[st.slots[i.holder]] : void 0;
877
+ return {
878
+ document: {
879
+ address: d.address,
880
+ name: d.name,
881
+ title: d.title,
882
+ version: d.version,
883
+ shown: shown(),
884
+ versions: d.versions,
885
+ by: d.by,
886
+ updated_at: d.updated_at,
887
+ link: d.link
888
+ },
889
+ repo: i.repo,
890
+ issue: {
891
+ address: i.address,
892
+ title: i.title,
893
+ type: i.type,
894
+ state: i.state,
895
+ holder: i.holder,
896
+ plans: i.plans.map(({ name, link, approved_at, approved_version }) => ({
897
+ name,
898
+ link,
899
+ approved_at,
900
+ approved_version
901
+ }))
902
+ },
903
+ slot: holder ? {
904
+ slot: i.holder,
905
+ stage: holder.stage,
906
+ status: holder.status,
907
+ state: holder.state
908
+ } : null,
909
+ live: page.live
910
+ };
911
+ });
912
+ async function send() {
913
+ const a = asked;
914
+ const out = await page.act({
915
+ type: a.type,
916
+ body: a.body
917
+ });
918
+ if (out.error) {
919
+ askNote = out.error;
920
+ return false;
921
+ }
922
+ a.id;
923
+ asked = null;
924
+ }
925
+ let $$settled = true;
926
+ let $$inner_renderer;
927
+ function $$render_inner($$renderer3) {
928
+ $$renderer3.push(`<div class="content-stack doc-view" data-view="doc"${attr("data-doc", d.address)}><div class="page-head"><div class="titles"><div class="title-row"><h1 class="title">${escape_html(d.title)}</h1> <span data-test="doc-live">`);
929
+ Badge($$renderer3, {
930
+ tone: page.live ? "success" : "warning",
931
+ dot: true,
932
+ children: ($$renderer4) => {
933
+ $$renderer4.push(`<!---->${escape_html(page.live ? "Live" : "Offline")}`);
934
+ },
935
+ $$slots: { default: true }
936
+ });
937
+ $$renderer3.push(`<!----></span></div> <div class="row-line body-sm sub"><a class="mono-sm"${attr("href", issueHash(i.address))}>${escape_html(i.address)}</a> `);
938
+ Badge($$renderer3, {
939
+ tone: STATE_BADGE[i.state].tone,
940
+ children: ($$renderer4) => {
941
+ $$renderer4.push(`<!---->${escape_html(STATE_BADGE[i.state].label)}`);
942
+ },
943
+ $$slots: { default: true }
944
+ });
945
+ $$renderer3.push(`<!----> <span>${escape_html(i.title)}</span></div> <p class="body-sm sub" data-test="doc-meta">by <span class="mono-sm">`);
946
+ SlotLink($$renderer3, { slot: d.by });
947
+ $$renderer3.push(`<!----></span> \xB7 <span class="mono-sm">${escape_html(d.name)}</span> \xB7 version ${escape_html(shown())}${escape_html(shown() !== d.version ? ` of ${d.version}` : "")} \xB7 updated ${escape_html(ago(d.updated_at))}</p> `);
948
+ if (d.versions.length > 1) {
949
+ $$renderer3.push(`<!--[0--><div class="row-line body-sm sub" data-test="doc-versions"><span>Versions</span> <!--[-->`);
950
+ const each_array = ensure_array_like(d.versions);
951
+ for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
952
+ let v = each_array[$$index];
953
+ Button($$renderer3, {
954
+ variant: v === shown() ? "secondary" : "quiet",
955
+ size: "sm",
956
+ "data-doc-version": v,
957
+ onclick: () => picked = v,
958
+ children: ($$renderer4) => {
959
+ $$renderer4.push(`<!---->${escape_html(v)}`);
960
+ },
961
+ $$slots: { default: true }
962
+ });
963
+ }
964
+ $$renderer3.push(`<!--]--></div>`);
965
+ } else $$renderer3.push("<!--[-1-->");
966
+ $$renderer3.push(`<!--]--></div> <div class="actions">`);
967
+ if (p()) {
968
+ $$renderer3.push(`<!--[0--><span data-test="doc-plan-state">`);
969
+ Badge($$renderer3, {
970
+ tone: p().approved_at && !approvedOther() ? "success" : "warning",
971
+ children: ($$renderer4) => {
972
+ $$renderer4.push(`<!---->${escape_html(p().approved_at ? approvedOther() ? `Approved version ${p().approved_version}, now ${d.version}` : "Plan approved" : "Plan not approved yet")}`);
973
+ },
974
+ $$slots: { default: true }
975
+ });
976
+ $$renderer3.push(`<!----></span> `);
977
+ if ((!p().approved_at || approvedOther()) && i.state !== "closed") {
978
+ $$renderer3.push("<!--[0-->");
979
+ Button($$renderer3, {
980
+ variant: "primary",
981
+ "data-approve-plan": p().link,
982
+ onclick: () => page.act({
983
+ type: "issue_plan",
984
+ body: {
985
+ issue: i.address,
986
+ link: p().link,
987
+ approved: true
988
+ }
989
+ }),
990
+ icon: Circle_check,
991
+ children: ($$renderer4) => {
992
+ $$renderer4.push(`<!---->Approve plan`);
993
+ },
994
+ $$slots: { default: true }
995
+ });
996
+ } else $$renderer3.push("<!--[-1-->");
997
+ $$renderer3.push(`<!--]-->`);
998
+ } else $$renderer3.push("<!--[-1-->");
999
+ $$renderer3.push(`<!--]--> `);
1000
+ if (!standalone) {
1001
+ $$renderer3.push("<!--[0-->");
1002
+ Button($$renderer3, {
1003
+ variant: "secondary",
1004
+ "data-doc-open": d.address,
1005
+ onclick: () => window.open(d.link, "_blank", "noopener"),
1006
+ icon: External_link,
1007
+ children: ($$renderer4) => {
1008
+ $$renderer4.push(`<!---->Open in new tab`);
1009
+ },
1010
+ $$slots: { default: true }
1011
+ });
1012
+ } else $$renderer3.push("<!--[-1-->");
1013
+ $$renderer3.push(`<!--]--></div></div> <iframe class="doc-frame"${attr("title", d.title)}${attr("src", src())}${attr("sandbox", DOC_SANDBOX)}></iframe></div> `);
1014
+ Dialog($$renderer3, {
1015
+ id: "doc-ask",
1016
+ form: "doc-ask-form",
1017
+ title: "This document asks to act as you",
1018
+ sub: "It is sent only if you choose Send.",
1019
+ icon: "shield",
1020
+ action: "Send",
1021
+ note: askNote,
1022
+ onsubmit: send,
1023
+ get open() {
1024
+ return askOpen;
1025
+ },
1026
+ set open($$value) {
1027
+ askOpen = $$value;
1028
+ $$settled = false;
1029
+ },
1030
+ children: ($$renderer4) => {
1031
+ if (asked) $$renderer4.push(`<!--[0--><p class="body">${escape_html(d.title)} asks to send <span class="mono-sm" data-test="doc-ask-type">${escape_html(asked.type)}</span> as you:</p> <pre class="mono-sm doc-ask-body" data-test="doc-ask-body">${escape_html(JSON.stringify(asked.body, null, 2))}</pre>`);
1032
+ else $$renderer4.push("<!--[-1-->");
1033
+ $$renderer4.push(`<!--]-->`);
1034
+ },
1035
+ $$slots: { default: true }
1036
+ });
1037
+ $$renderer3.push(`<!---->`);
1038
+ }
1039
+ do {
1040
+ $$settled = true;
1041
+ $$inner_renderer = $$renderer2.copy();
1042
+ $$render_inner($$inner_renderer);
1043
+ } while (!$$settled);
1044
+ $$renderer2.subsume($$inner_renderer);
1045
+ });
1046
+ }
1047
+
1048
+ export {
1049
+ favicon_default,
1050
+ IconButton,
1051
+ Dialog$1,
1052
+ TYPE_BADGE,
1053
+ STATE_BADGE,
1054
+ WORK_PR_BADGE,
1055
+ LANDING_BADGE,
1056
+ ASK_LABEL,
1057
+ askedPlan,
1058
+ blockerBadge,
1059
+ leadOfIn,
1060
+ waitersOf,
1061
+ waitingOn,
1062
+ checkoutNotices,
1063
+ recordNotices,
1064
+ groupOf,
1065
+ docHash,
1066
+ stateOf,
1067
+ when,
1068
+ repoOf,
1069
+ issueHash,
1070
+ repoHash,
1071
+ changeHash,
1072
+ repoGithubUrl,
1073
+ repoSettingsHash,
1074
+ repoSecretsHash,
1075
+ slotSecretsHash,
1076
+ sessionHash,
1077
+ waiting,
1078
+ ago,
1079
+ hashOf,
1080
+ Page,
1081
+ providePage,
1082
+ usePage,
1083
+ Icon2 as Icon,
1084
+ Circle_check,
1085
+ External_link,
1086
+ SlotLink,
1087
+ colorStyle,
1088
+ Badge,
1089
+ Dialog,
1090
+ DocDetail
1091
+ };