gm-copilot-cli 2.0.537 → 2.0.539

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.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: gm
3
- version: 2.0.537
3
+ version: 2.0.539
4
4
  description: State machine agent with hooks, skills, and automated git enforcement
5
5
  author: AnEntrypoint
6
6
  repository: https://github.com/AnEntrypoint/gm-copilot-cli
package/index.html CHANGED
@@ -1,531 +1,175 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Copilot CLI - gm plugin</title>
7
- <script src="https://cdn.tailwindcss.com"></script>
8
-
9
- <style>
10
- body{background:#0f172a;color:#e2e8f0;font-family:system-ui,sans-serif;margin:0}
11
- .gradient-hero{background:linear-gradient(135deg,#0f172a 0%,#1e1b4b 50%,#0f172a 100%)}
12
- .card-hover{transition:transform .2s,box-shadow .2s}
13
- .card-hover:hover{transform:translateY(-2px);box-shadow:0 8px 30px rgba(0,0,0,.3)}
14
- pre{scrollbar-width:thin;background:#020617;border:1px solid #1e293b;border-radius:8px;padding:12px 16px;color:#4ade80;overflow-x:auto;font-size:.875rem}
15
- </style>
16
- </head>
17
- <body>
18
- <script>
19
- const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
20
- const MATH_NAMESPACE = "http://www.w3.org/1998/Math/MathML";
21
- const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
1
+ <!doctype html>
2
+ <html lang="en"><head>
3
+ <meta charset="utf-8">
4
+ <meta name="viewport" content="width=device-width,initial-scale=1">
5
+ <title>Copilot CLI · gm</title>
6
+ <meta name="description" content="State machine agent with hooks, skills, and automated git enforcement">
7
+ <meta name="color-scheme" content="light">
8
+ <meta name="theme-color" content="#EFE9DD">
9
+ <link rel="preconnect" href="https://fonts.googleapis.com">
10
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
+ <link href="https://fonts.googleapis.com/css2?family=Archivo:wght@400;600;700;800&family=JetBrains+Mono:wght@400;500;600;700&family=Space+Grotesk:wght@400;500;600&display=swap" rel="stylesheet">
12
+ <style>
13
+ @font-face{font-family:'Archivo';src:local('Archivo');}
14
+ :root{
15
+ --paper:#EFE9DD;--ink:#0B0B09;--acid:#B8FF00;--link:#1F4DFF;--warn:#FF3B1F;--live:#00A86B;
16
+ --fg:var(--ink);--bg:var(--paper);--fg-2:#3a3a36;--fg-3:#6b6b64;
17
+ --ff-display:'Archivo','Archivo Narrow',ui-sans-serif,sans-serif;
18
+ --ff-mono:'JetBrains Mono','ui-monospace',Menlo,Consolas,monospace;
19
+ --ff-body:'Space Grotesk','Archivo',ui-sans-serif,sans-serif;
20
+ --fs-hero:clamp(64px,12vw,144px);--fs-h1:clamp(40px,6vw,72px);--fs-h2:28px;--fs-h3:18px;--fs-h4:15px;
21
+ --fs-body:14px;--fs-lg:17px;--fs-xs:11px;--fs-micro:10px;
22
+ --lh-tight:1.02;--lh-snug:1.18;--lh-base:1.5;--lh-long:1.6;
23
+ --tr-tight:-0.02em;--tr-label:0.08em;
24
+ --space-1:4px;--space-2:8px;--space-3:12px;--space-4:16px;--space-5:24px;--space-6:32px;--space-7:48px;--space-8:64px;
25
+ --measure:64ch;
26
+ --dur-snap:80ms;--dur-base:160ms;--ease:cubic-bezier(0.2,0,0,1);
27
+ }
28
+ *,*::before,*::after{box-sizing:border-box;border:0;outline:0;border-radius:0;}
29
+ html,body{margin:0;padding:0;background:var(--paper);color:var(--ink);font-family:var(--ff-mono);font-size:var(--fs-body);line-height:var(--lh-base);-webkit-font-smoothing:antialiased;}
30
+ a{color:inherit;text-decoration:none;}
31
+ a:hover{text-decoration:underline;text-underline-offset:3px;}
32
+ .rule{border-top:1px solid var(--ink);height:0;margin:0;flex:1;}
33
+ .rule-double{border-top:3px double var(--ink);height:0;margin:0;}
34
+ .t-hero{font-family:var(--ff-display);font-size:var(--fs-hero);line-height:var(--lh-tight);letter-spacing:var(--tr-tight);font-weight:800;margin:0;text-transform:lowercase;}
35
+ .t-hero .slash{color:var(--fg-3);font-weight:400;margin:0 0.05em;}
36
+ h1,h2,h3{margin:0;font-family:var(--ff-display);}
37
+ .t-h2,h2{font-size:var(--fs-h2);line-height:var(--lh-snug);font-weight:700;letter-spacing:var(--tr-tight);}
38
+ .t-body{font-family:var(--ff-mono);font-size:var(--fs-body);line-height:var(--lh-base);}
39
+ .t-prose{font-family:var(--ff-body);font-size:var(--fs-lg);line-height:var(--lh-long);max-width:var(--measure);}
40
+ .t-label{font-family:var(--ff-mono);font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:var(--tr-label);font-weight:500;color:var(--fg-2);}
41
+ .t-micro{font-family:var(--ff-mono);font-size:var(--fs-micro);letter-spacing:var(--tr-label);text-transform:uppercase;color:var(--fg-3);}
42
+ .t-meta{font-family:var(--ff-mono);font-size:var(--fs-xs);color:var(--fg-3);}
22
43
 
23
- const Fragment = (props) => {
24
- return props.children
25
- ? Array.isArray(props.children)
26
- ? props.children
27
- : [props.children]
28
- : [];
29
- };
44
+ .stamp{display:inline-block;padding:var(--space-1) var(--space-3);font-family:var(--ff-mono);font-size:var(--fs-xs);letter-spacing:var(--tr-label);text-transform:uppercase;font-weight:600;transform:rotate(-2deg);}
45
+ .stamp.ink{background:var(--ink);color:var(--paper);}
46
+ .stamp.acid{background:var(--acid);color:var(--ink);}
30
47
 
31
- /**
32
- * Handles event listener updates for an element
33
- */
34
- function updateEventListener(el, eventName, newHandler, oldHandler) {
35
- if (oldHandler && oldHandler !== newHandler) {
36
- el.removeEventListener(eventName, oldHandler);
37
- }
38
- if (newHandler && oldHandler !== newHandler) {
39
- el.addEventListener(eventName, newHandler);
40
- el.__webjsx_listeners = {
41
- ...(el.__webjsx_listeners || {}),
42
- [eventName]: newHandler,
43
- };
44
- }
45
- }
46
- /**
47
- * Updates a single property or attribute on an element
48
- */
49
- function updatePropOrAttr(el, key, value) {
50
- if (el instanceof HTMLElement) {
51
- if (key in el) {
52
- // Fast path: property exists on HTMLElement
53
- el[key] = value;
54
- return;
55
- }
56
- if (typeof value === "string") {
57
- el.setAttribute(key, value);
58
- return;
59
- }
60
- // Fallback for non-string values on HTMLElement
61
- el[key] = value;
62
- return;
63
- }
64
- // SVG/Other namespace elements
65
- const isSVG = el.namespaceURI === "http://www.w3.org/2000/svg";
66
- if (isSVG) {
67
- if (value != null) {
68
- el.setAttribute(key, value.toString());
69
- }
70
- else {
71
- el.removeAttribute(key);
72
- }
73
- return;
74
- }
75
- // Fallback for other element types
76
- if (typeof value === "string") {
77
- el.setAttribute(key, value);
78
- }
79
- else {
80
- el[key] = value;
81
- }
82
- }
83
- /**
84
- * Handles suspension of rendering during updates
85
- */
86
- function withRenderSuspension(el, callback) {
87
- const isRenderingSuspended = !!el
88
- .__webjsx_suspendRendering;
89
- if (isRenderingSuspended) {
90
- el.__webjsx_suspendRendering();
91
- }
92
- try {
93
- return callback();
94
- }
95
- finally {
96
- if (isRenderingSuspended) {
97
- el.__webjsx_resumeRendering();
98
- }
99
- }
100
- }
101
- /**
102
- * Core function to update attributes and properties on a DOM element
103
- */
104
- function updateAttributesCore(el, newProps, oldProps = {}) {
105
- // Handle new/updated props
106
- for (const [key, value] of Object.entries(newProps)) {
107
- if (key === "children" ||
108
- key === "key" ||
109
- key === "dangerouslySetInnerHTML")
110
- continue;
111
- if (key.startsWith("on") && typeof value === "function") {
112
- const eventName = key.substring(2).toLowerCase();
113
- updateEventListener(el, eventName, value, el.__webjsx_listeners?.[eventName]);
114
- }
115
- else if (value !== oldProps[key]) {
116
- updatePropOrAttr(el, key, value);
117
- }
118
- }
119
- // Handle dangerouslySetInnerHTML
120
- if ("dangerouslySetInnerHTML" in newProps) {
121
- const html = newProps.dangerouslySetInnerHTML.__html || "";
122
- el.innerHTML = html;
123
- }
124
- else if ("dangerouslySetInnerHTML" in oldProps) {
125
- el.innerHTML = "";
126
- }
127
- // If this is a fresh set (no oldProps), remove any attributes not in newProps
128
- if (Object.keys(oldProps).length === 0) {
129
- const currentAttrs = Array.from(el.attributes).map((attr) => attr.name);
130
- for (const attr of currentAttrs) {
131
- if (!(attr in newProps) && !attr.startsWith("on")) {
132
- el.removeAttribute(attr);
133
- }
134
- }
135
- }
136
- // Remove old props/attributes
137
- for (const key of Object.keys(oldProps)) {
138
- if (!(key in newProps) &&
139
- key !== "children" &&
140
- key !== "key" &&
141
- key !== "dangerouslySetInnerHTML") {
142
- if (key.startsWith("on")) {
143
- const eventName = key.substring(2).toLowerCase();
144
- const existingListener = el.__webjsx_listeners?.[eventName];
145
- if (existingListener) {
146
- el.removeEventListener(eventName, existingListener);
147
- delete el.__webjsx_listeners[eventName];
148
- }
149
- }
150
- else if (key in el) {
151
- el[key] = undefined;
152
- }
153
- else {
154
- el.removeAttribute(key);
155
- }
156
- }
157
- }
158
- // Store current props for future updates
159
- el.__webjsx_props = newProps;
160
- }
161
- /**
162
- * Sets attributes and properties on a DOM element based on the provided props.
163
- * If the property exists on the element, it sets it as a property.
164
- * Otherwise, it sets it as an attribute or property based on the value type.
165
- *
166
- * @param el - The DOM element to update.
167
- * @param props - The new properties to apply.
168
- */
169
- function setAttributes(el, props) {
170
- withRenderSuspension(el, () => {
171
- updateAttributesCore(el, props);
172
- });
173
- }
174
- /**
175
- * Updates attributes and properties on a DOM element based on the new and old props.
176
- *
177
- * @param el - The DOM element to update.
178
- * @param newProps - The new properties to apply.
179
- * @param oldProps - The old properties to compare against.
180
- */
181
- function updateAttributes(el, newProps, oldProps) {
182
- withRenderSuspension(el, () => {
183
- updateAttributesCore(el, newProps, oldProps);
184
- });
185
- }
48
+ .btn-stamp{display:inline-flex;align-items:center;gap:var(--space-2);padding:var(--space-3) var(--space-4);background:var(--ink);color:var(--paper);box-shadow:4px 4px 0 var(--ink);font-family:var(--ff-mono);font-weight:600;font-size:var(--fs-body);text-transform:uppercase;letter-spacing:var(--tr-label);cursor:pointer;transition:transform var(--dur-snap) var(--ease),box-shadow var(--dur-snap) var(--ease);}
49
+ .btn-stamp:hover{transform:translate(1px,1px);box-shadow:3px 3px 0 var(--ink);text-decoration:none;}
50
+ .btn-stamp:active{transform:translate(4px,4px);box-shadow:0 0 0 var(--ink);}
186
51
 
187
- function isFragment(type) {
188
- return type === Fragment;
189
- }
190
- function createNode(vnode, parentNamespaceURI) {
191
- if (typeof vnode === "string" ||
192
- typeof vnode === "number" ||
193
- typeof vnode === "boolean") {
194
- return document.createTextNode(String(vnode));
195
- }
196
- else if (isFragment(vnode.type)) {
197
- const fragment = document.createDocumentFragment();
198
- if (vnode.props.children) {
199
- const children = vnode.props.children;
200
- children.forEach((child) => {
201
- fragment.appendChild(createNode(child, undefined));
202
- });
203
- }
204
- return fragment;
205
- }
206
- else {
207
- const namespaceURI = vnode.props.xmlns !== undefined
208
- ? vnode.props.xmlns
209
- : vnode.type === "svg"
210
- ? SVG_NAMESPACE
211
- : parentNamespaceURI ?? undefined;
212
- const el = vnode.props.is !== undefined
213
- ? namespaceURI !== undefined
214
- ? document.createElementNS(namespaceURI, vnode.type, {
215
- is: vnode.props.is,
216
- })
217
- : document.createElement(vnode.type, {
218
- is: vnode.props.is,
219
- })
220
- : namespaceURI !== undefined
221
- ? document.createElementNS(namespaceURI, vnode.type)
222
- : document.createElement(vnode.type);
223
- if (vnode.props) {
224
- setAttributes(el, vnode.props);
225
- }
226
- if (vnode.props.key != null) {
227
- el.__webjsx_key = vnode.props.key;
228
- el.setAttribute("data-key", String(vnode.props.key));
229
- }
230
- if (vnode.props.ref) {
231
- assignRef(el, vnode.props.ref);
232
- }
233
- if (vnode.props.children && !vnode.props.dangerouslySetInnerHTML) {
234
- const children = vnode.props.children;
235
- children.forEach((child) => {
236
- el.appendChild(createNode(child, namespaceURI));
237
- });
238
- }
239
- return el;
240
- }
241
- }
242
- /**
243
- * Assigns a ref to a node.
244
- * @param node The DOM node.
245
- * @param ref The ref to assign.
246
- */
247
- function assignRef(node, ref) {
248
- const currentRef = node.__webjsx_assignedRef;
249
- // Only assign the ref if it's different
250
- if (currentRef !== ref) {
251
- if (typeof ref === "function") {
252
- ref(node);
253
- }
254
- else if (ref && typeof ref === "object") {
255
- ref.current = node;
256
- }
257
- // Store the assigned ref
258
- node.__webjsx_assignedRef = ref;
259
- }
260
- }
52
+ .app-top{position:sticky;top:0;z-index:10;background:var(--paper);display:flex;align-items:center;gap:var(--space-4);padding:var(--space-3) var(--space-5);border-bottom:1px solid var(--ink);}
53
+ .app-top .brand{font-family:var(--ff-mono);font-weight:700;text-transform:uppercase;letter-spacing:var(--tr-label);}
54
+ .app-top .brand .slash{color:var(--fg-3);margin:0 var(--space-1);}
55
+ .app-top nav{margin-left:auto;display:flex;gap:var(--space-4);font-family:var(--ff-mono);font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:var(--tr-label);}
261
56
 
262
- function createElement(type, props, ...children) {
263
- const normalizedProps = props ? { ...props } : {};
264
- const flatChildren = [];
265
- const flatten = (child) => {
266
- if (Array.isArray(child)) {
267
- child.forEach(flatten);
268
- }
269
- else if (typeof child === "string" || typeof child === "number") {
270
- flatChildren.push(child);
271
- }
272
- else if (child === null ||
273
- child === undefined ||
274
- typeof child === "boolean") {
275
- // Ignore null or undefined children
276
- }
277
- else {
278
- flatChildren.push(child);
279
- }
280
- };
281
- children.forEach(flatten);
282
- if (flatChildren.length > 0) {
283
- // Only set children if dangerouslySetInnerHTML is not present
284
- if (!normalizedProps.dangerouslySetInnerHTML) {
285
- normalizedProps.children = flatChildren;
286
- }
287
- else {
288
- console.warn("WebJSX: Ignoring children since dangerouslySetInnerHTML is set.");
289
- }
290
- }
291
- return {
292
- type,
293
- props: normalizedProps,
294
- };
295
- }
57
+ .dateline{display:flex;gap:var(--space-5);flex-wrap:wrap;padding:var(--space-2) var(--space-5);border-bottom:1px solid var(--ink);background:var(--paper);}
58
+ .page{max-width:1100px;margin:0 auto;padding:0 var(--space-5);}
59
+ .hero{padding:var(--space-8) 0 var(--space-7) 0;}
60
+ .hero .stamp{margin-bottom:var(--space-4);}
61
+ .hero .lede{margin-top:var(--space-4);color:var(--fg-2);}
62
+ .hero-cta{margin-top:var(--space-6);}
296
63
 
297
- /**
298
- * Applies the differences between the new virtual node(s) and the existing DOM.
299
- * @param parent The parent DOM node where the virtual nodes will be applied.
300
- * @param newVirtualNode A single virtual node or an array of virtual nodes.
301
- */
302
- function applyDiff(parent, newVirtualNode) {
303
- const newVNodes = Array.isArray(newVirtualNode)
304
- ? newVirtualNode
305
- : [newVirtualNode];
306
- diffChildren(parent, newVNodes);
307
- }
308
- /**
309
- * Flattens the list of virtual nodes by replacing Fragments with their children.
310
- * @param vnodes The array of virtual nodes to flatten.
311
- * @returns A new array of virtual nodes with Fragments flattened.
312
- */
313
- function flattenVNodes(vnodes) {
314
- const flat = [];
315
- const arrayVNodes = vnodes;
316
- arrayVNodes.forEach((vnode) => {
317
- if (isFragment(vnode)) {
318
- const children = vnode.props.children ? vnode.props.children : [];
319
- flat.push(...children);
320
- }
321
- else {
322
- flat.push(vnode);
323
- }
324
- });
325
- return flat;
326
- }
327
- /**
328
- * Type guard to check if a VNode is a Fragment.
329
- * @param vnode The virtual node to check.
330
- * @returns True if vnode is a Fragment, false otherwise.
331
- */
332
- function isFragment(vnode) {
333
- return typeof vnode === "object" && vnode !== null && vnode.type === Fragment;
334
- }
335
- /**
336
- * Diffs and updates the children of a DOM node based on the new virtual nodes.
337
- * @param parent The parent DOM node whose children will be diffed.
338
- * @param newVNodes An array of new virtual nodes.
339
- */
340
- function diffChildren(parent, newVNodes) {
341
- const flattenedVNodes = flattenVNodes(newVNodes);
342
- const existingNodes = Array.from(parent.childNodes);
343
- const keyedMap = new Map();
344
- // Populate keyedMap with existing keyed nodes
345
- existingNodes.forEach((node) => {
346
- const key = node.__webjsx_key;
347
- if (key != null) {
348
- keyedMap.set(key, node);
349
- }
350
- });
351
- const newKeys = flattenedVNodes
352
- .filter(isVElementWithKey)
353
- .map((vnode) => vnode.props.key);
354
- existingNodes.forEach((node) => {
355
- const key = node.__webjsx_key;
356
- if (key != null && !newKeys.includes(key)) {
357
- parent.removeChild(node);
358
- }
359
- });
360
- flattenedVNodes.forEach((newVNode, i) => {
361
- const newKey = isVElement(newVNode) ? newVNode.props.key : undefined;
362
- let existingNode = null;
363
- if (newKey != null) {
364
- existingNode = keyedMap.get(newKey) || null;
365
- }
366
- if (!existingNode && newKey == null) {
367
- existingNode = parent.childNodes[i] || null;
368
- }
369
- if (existingNode) {
370
- if (existingNode !== parent.childNodes[i]) {
371
- parent.insertBefore(existingNode, parent.childNodes[i] || null);
372
- }
373
- updateNode(existingNode, newVNode);
374
- }
375
- else {
376
- const newDomNode = createNode(newVNode, getNamespaceURI(parent));
377
- if (isVElement(newVNode) && newVNode.props.key != null) {
378
- newDomNode.__webjsx_key = newVNode.props.key;
379
- newDomNode.setAttribute("data-key", String(newVNode.props.key));
380
- }
381
- parent.insertBefore(newDomNode, parent.childNodes[i] || null);
382
- }
383
- });
384
- const updatedChildNodes = Array.from(parent.childNodes);
385
- const newUnkeyed = flattenedVNodes.filter((vnode) => !isVElementWithKey(vnode));
386
- const existingUnkeyed = updatedChildNodes.filter((node) => !node.__webjsx_key);
387
- if (newUnkeyed.length < existingUnkeyed.length) {
388
- for (let i = newUnkeyed.length; i < existingUnkeyed.length; i++) {
389
- parent.removeChild(existingUnkeyed[i]);
390
- }
391
- }
392
- }
393
- /**
394
- * Updates a DOM node to match the new virtual node.
395
- * @param domNode The existing DOM node to be updated.
396
- * @param newVNode The new virtual node to apply.
397
- */
398
- function updateNode(domNode, newVNode) {
399
- if (typeof newVNode === "string" ||
400
- typeof newVNode === "number" ||
401
- typeof newVNode === "boolean") {
402
- if (domNode.nodeType !== Node.TEXT_NODE ||
403
- domNode.textContent !== String(newVNode)) {
404
- const newTextNode = document.createTextNode(String(newVNode));
405
- domNode.parentNode?.replaceChild(newTextNode, domNode);
406
- }
407
- return;
408
- }
409
- if (newVNode.type === Fragment) {
410
- if (domNode instanceof DocumentFragment) {
411
- diffChildren(domNode, newVNode.props.children ? newVNode.props.children : []);
412
- }
413
- else {
414
- const fragment = document.createDocumentFragment();
415
- const children = newVNode.props.children ? newVNode.props.children : [];
416
- children.forEach((child) => {
417
- fragment.appendChild(createNode(child, undefined));
418
- });
419
- domNode.parentNode?.replaceChild(fragment, domNode);
420
- }
421
- return;
422
- }
423
- if (domNode instanceof HTMLElement &&
424
- domNode.tagName.toLowerCase() === newVNode.type.toLowerCase()) {
425
- const oldProps = domNode.__webjsx_props || {};
426
- const newProps = newVNode.props || {};
427
- updateAttributes(domNode, newProps, oldProps);
428
- if (isVElement(newVNode) && newVNode.props.key != null) {
429
- domNode.__webjsx_key = newVNode.props.key;
430
- domNode.setAttribute("data-key", String(newVNode.props.key));
431
- }
432
- else {
433
- delete domNode.__webjsx_key;
434
- domNode.removeAttribute("data-key");
435
- }
436
- if (newProps.ref) {
437
- assignRef(domNode, newProps.ref);
438
- }
439
- if (!newProps.dangerouslySetInnerHTML && newProps.children != null) {
440
- diffChildren(domNode, newProps.children);
441
- }
442
- }
443
- else {
444
- const newDomNode = createNode(newVNode, domNode.parentNode ? getNamespaceURI(domNode.parentNode) : undefined);
445
- if (isVElement(newVNode) && newVNode.props.key != null) {
446
- newDomNode.__webjsx_key = newVNode.props.key;
447
- newDomNode.setAttribute("data-key", String(newVNode.props.key));
448
- }
449
- if (isVElement(newVNode) && newVNode.props.ref) {
450
- assignRef(newDomNode, newVNode.props.ref);
451
- }
452
- domNode.parentNode?.replaceChild(newDomNode, domNode);
453
- }
454
- }
455
- /**
456
- * Assigns a ref to a node.
457
- * @param node The DOM node.
458
- * @param ref The ref to assign.
459
- */
460
- function assignRef(node, ref) {
461
- const currentRef = node.__webjsx_assignedRef;
462
- // Only assign the ref if it's different
463
- if (currentRef !== ref) {
464
- if (typeof ref === "function") {
465
- ref(node);
466
- }
467
- else if (ref && typeof ref === "object") {
468
- ref.current = node;
469
- }
470
- // Store the assigned ref
471
- node.__webjsx_assignedRef = ref;
472
- }
473
- }
474
- /**
475
- * Type guard to check if a VNode is a VElement.
476
- * @param vnode The virtual node to check.
477
- * @returns True if vnode is a VElement, false otherwise.
478
- */
479
- function isVElement(vnode) {
480
- return typeof vnode === "object" && vnode !== null && "props" in vnode;
481
- }
482
- /**
483
- * Type guard to check if a VNode is a VElement with a key.
484
- * @param vnode The virtual node to check.
485
- * @returns True if vnode is a VElement with a key, false otherwise.
486
- */
487
- function isVElementWithKey(vnode) {
488
- return isVElement(vnode) && vnode.props.key != null;
489
- }
490
- function getNamespaceURI(node) {
491
- return node instanceof Element && node.namespaceURI !== HTML_NAMESPACE
492
- ? node.namespaceURI ?? undefined
493
- : undefined;
494
- }
64
+ .section{padding:var(--space-7) 0;border-top:1px solid var(--ink);}
65
+ .section-head{display:flex;align-items:center;gap:var(--space-4);margin-bottom:var(--space-5);}
66
+ .section-lede{margin-bottom:var(--space-5);color:var(--fg-2);}
67
+
68
+ .receipt{border:1px solid var(--ink);background:color-mix(in srgb,var(--paper) 94%,var(--ink));}
69
+ .receipt-row{display:grid;grid-template-columns:48px 1fr;gap:var(--space-4);padding:var(--space-4);border-bottom:1px dashed var(--ink);}
70
+ .receipt-row:last-child{border-bottom:0;}
71
+ .receipt-row .num{align-self:start;padding-top:2px;}
72
+ .receipt-cmd{font-family:var(--ff-mono);font-size:var(--fs-body);background:var(--ink);color:var(--acid);padding:var(--space-3);margin:var(--space-2) 0 0 0;overflow-x:auto;}
73
+ .receipt-cmd code{background:transparent;color:inherit;}
495
74
 
496
- const h = createElement;
75
+ .feat-list,.phase-list,.idx-list{list-style:none;margin:0;padding:0;}
76
+ .feat-row,.phase-row{display:grid;grid-template-columns:180px 1fr;gap:var(--space-4);padding:var(--space-3) 0;border-top:1px solid var(--ink);}
77
+ .feat-row:last-child,.phase-row:last-child{border-bottom:1px solid var(--ink);}
78
+ .feat-tag,.phase-name{padding-top:2px;}
497
79
 
498
- const PLATFORM_NAME="Copilot CLI",PLATFORM_TYPE="CLI Tool",PLATFORM_TYPE_COLOR="#3b82f6";
499
- const DESCRIPTION="State machine agent with hooks, skills, and automated git enforcement",VERSION="2.0.537";
500
- const GITHUB_URL="https://github.com/AnEntrypoint/gm-copilot-cli",BADGE_LABEL="copilot-cli";
501
- const FEATURES=[{"title":"State Machine","desc":"Immutable PLAN→EXECUTE→EMIT→VERIFY→COMPLETE phases with full mutable tracking"},{"title":"Semantic Search","desc":"Natural language codebase exploration via codesearch skill — no grep needed"},{"title":"Hooks","desc":"Pre-tool, session-start, prompt-submit, and stop hooks for full lifecycle control"},{"title":"Agents","desc":"gm, codesearch, and websearch agents pre-configured and ready to use"},{"title":"MCP Integration","desc":"Model Context Protocol server support built in"},{"title":"Auto-Recovery","desc":"Supervisor hierarchy ensures the system never crashes"}],INSTALL_STEPS=[{"desc":"Install via GitHub CLI","cmd":"gh extension install AnEntrypoint/gm-copilot-cli"},{"desc":"Restart your terminal — activates automatically"}];
502
- const CURRENT_PLATFORM="gm-copilot-cli";
503
- const ALL_PLATFORMS=[
504
- {id:'gm-cc',label:'Claude Code',type:'cli'},{id:'gm-gc',label:'Gemini CLI',type:'cli'},
505
- {id:'gm-oc',label:'OpenCode',type:'cli'},{id:'gm-kilo',label:'Kilo Code',type:'cli'},
506
- {id:'gm-codex',label:'Codex',type:'cli'},{id:'gm-copilot-cli',label:'Copilot CLI',type:'cli'},
507
- {id:'gm-qwen',label:'Qwen Code',type:'cli'},{id:'gm-hermes',label:'Hermes Agent',type:'cli'},
508
- {id:'gm-vscode',label:'VS Code',type:'ide'},{id:'gm-cursor',label:'Cursor',type:'ide'},
509
- {id:'gm-zed',label:'Zed',type:'ide'},{id:'gm-jetbrains',label:'JetBrains',type:'ide'},
510
- ];
511
- const GH_ICON='M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z';
512
- function NavBar(){return h('nav',{class:'border-b border-gray-800 bg-gray-950/80 backdrop-blur sticky top-0 z-10'},h('div',{class:'max-w-5xl mx-auto px-4 py-3 flex items-center justify-between'},h('div',{class:'flex items-center gap-3'},h('a',{href:'https://anentrypoint.github.io/gm',class:'text-white font-bold text-lg hover:text-indigo-400 transition-colors'},'gm'),h('span',{class:'text-gray-500'},'/'),h('span',{class:'text-gray-300 font-medium'},BADGE_LABEL)),h('a',{href:GITHUB_URL,target:'_blank',rel:'noopener',class:'flex items-center gap-2 text-gray-400 hover:text-white transition-colors text-sm'},h('svg',{viewBox:'0 0 16 16',class:'w-5 h-5 fill-current','aria-hidden':'true'},h('path',{d:GH_ICON})),'GitHub')));}
513
- function Badge(label,color){return h('span',{class:'inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold text-white',style:`background-color:${color}`},label);}
514
- function Hero(){return h('section',{class:'gradient-hero py-20 px-4'},h('div',{class:'max-w-5xl mx-auto text-center'},h('div',{class:'flex justify-center gap-2 mb-6'},Badge(PLATFORM_TYPE,PLATFORM_TYPE_COLOR),Badge('v'+VERSION,'#374151')),h('h1',{class:'text-4xl md:text-5xl font-bold text-white mb-4'},PLATFORM_NAME),h('p',{class:'text-lg text-gray-300 max-w-2xl mx-auto mb-8'},DESCRIPTION),h('a',{href:GITHUB_URL,target:'_blank',rel:'noopener',class:'inline-flex items-center gap-2 bg-indigo-600 hover:bg-indigo-500 text-white font-semibold px-6 py-3 rounded-lg transition-colors'},'View on GitHub')));}
515
- function FeatureCard(title,desc){return h('div',{class:'card-hover bg-gray-900 border border-gray-800 rounded-xl p-5'},h('h3',{class:'font-semibold text-white mb-2'},title),h('p',{class:'text-gray-400 text-sm leading-relaxed'},desc));}
516
- function FeaturesSection(){return h('section',{class:'py-16 px-4'},h('div',{class:'max-w-5xl mx-auto'},h('h2',{class:'text-2xl font-bold text-white mb-8 text-center'},'Features'),h('div',{class:'grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4'},...FEATURES.map(f=>FeatureCard(f.title,f.desc)))));}
517
- function InstallStep(step,index){return h('div',{class:'flex gap-4 items-start'},h('div',{class:'flex-shrink-0 w-7 h-7 rounded-full bg-indigo-600 flex items-center justify-center text-xs font-bold text-white'},String(index+1)),h('div',{class:'flex-1'},h('p',{class:'text-gray-300 text-sm mb-1'},step.desc),step.cmd?h('pre',{class:'bg-gray-950 border border-gray-700 rounded-lg px-4 py-2 text-sm text-green-400 overflow-x-auto mt-1'},step.cmd):null));}
518
- function InstallSection(){if(!INSTALL_STEPS.length)return null;return h('section',{class:'py-16 px-4 bg-gray-900/50'},h('div',{class:'max-w-2xl mx-auto'},h('h2',{class:'text-2xl font-bold text-white mb-8 text-center'},'Installation'),h('div',{class:'space-y-6'},...INSTALL_STEPS.map((step,i)=>InstallStep(step,i)))));}
519
- function PlatformLink(p){const isCurrent=p.id===CURRENT_PLATFORM;return h('a',{href:isCurrent?'#':`https://anentrypoint.github.io/${p.id}`,class:`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${isCurrent?'bg-indigo-600 text-white cursor-default':'bg-gray-800 text-gray-300 hover:bg-gray-700 hover:text-white'}`},p.label);}
520
- const SM_PHASES=[{name:'PLAN',desc:'Write .prd with every unknown named before any work begins'},{name:'EXECUTE',desc:'Prove every hypothesis via witnessed execution, import real modules'},{name:'EMIT',desc:'Write files only after all tests pass — pre and post-emit gates'},{name:'VERIFY',desc:'End-to-end execution confirms all changes work in real context'},{name:'COMPLETE',desc:'.prd empty, git clean, all output pushed'}];
521
- const HOOK_ITEMS=[{title:'Tool interception',desc:'exec:<lang> commands run code directly; forbidden tools redirected to code-search'},{title:'System injection',desc:'gm.md rules prepended to every system prompt'},{title:'Context injection',desc:'session-start injects codebase analysis and pending work reminder'},{title:'Completion gate',desc:'session end blocked until .prd is empty and git is clean'}];
522
- function PhaseCard(phase,index,total){return h('div',{class:'card-hover bg-gray-900 border border-gray-800 rounded-xl p-4 flex-1 min-w-0'},h('div',{class:'flex items-center gap-2 mb-2'},h('span',{class:'text-indigo-400 font-bold text-sm font-mono'},phase.name),index<total-1?h('span',{class:'text-gray-600 text-xs'},'→'):null),h('p',{class:'text-gray-400 text-xs leading-relaxed'},phase.desc));}
523
- function StateMachineSection(){return h('section',{class:'py-16 px-4 bg-gray-900/40'},h('div',{class:'max-w-5xl mx-auto'},h('h2',{class:'text-2xl font-bold text-white mb-2 text-center'},'State Machine'),h('p',{class:'text-gray-400 text-sm text-center mb-8'},'Every task follows the same 5-phase cycle — no skipping, no shortcuts'),h('div',{class:'flex flex-col sm:flex-row gap-3'},...SM_PHASES.map((phase,i)=>PhaseCard(phase,i,SM_PHASES.length)))));}
524
- function HookCard(item){return h('div',{class:'card-hover bg-gray-900 border border-gray-800 rounded-xl p-5'},h('h3',{class:'font-semibold text-white mb-2'},item.title),h('p',{class:'text-gray-400 text-sm leading-relaxed'},item.desc));}
525
- function HooksSection(){return h('section',{class:'py-16 px-4'},h('div',{class:'max-w-5xl mx-auto'},h('h2',{class:'text-2xl font-bold text-white mb-2 text-center'},'What the Hooks Enforce'),h('p',{class:'text-gray-400 text-sm text-center mb-8'},'Lifecycle hooks wrap every interaction to keep the agent on rails'),h('div',{class:'grid grid-cols-1 sm:grid-cols-2 gap-4'},...HOOK_ITEMS.map(item=>HookCard(item)))));}
526
- function AlsoAvailableSection(){const cli=ALL_PLATFORMS.filter(p=>p.type==='cli'),ide=ALL_PLATFORMS.filter(p=>p.type==='ide');return h('section',{class:'py-16 px-4 bg-gray-900/30'},h('div',{class:'max-w-5xl mx-auto'},h('h2',{class:'text-2xl font-bold text-white mb-8 text-center'},'Also Available For'),h('div',{class:'space-y-6'},h('div',null,h('p',{class:'text-xs font-semibold text-blue-400 uppercase tracking-wider mb-3'},'CLI Tools'),h('div',{class:'flex flex-wrap gap-2'},...cli.map(p=>PlatformLink(p)))),h('div',null,h('p',{class:'text-xs font-semibold text-purple-400 uppercase tracking-wider mb-3'},'IDE Extensions'),h('div',{class:'flex flex-wrap gap-2'},...ide.map(p=>PlatformLink(p))))),h('div',{class:'mt-8 text-center'},h('a',{href:'https://anentrypoint.github.io/gm',class:'text-sm text-gray-400 hover:text-indigo-300 transition-colors'},'← Back to gm hub'))));}
527
- function Footer(){return h('footer',{class:'border-t border-gray-800 py-8 px-4 text-center text-gray-500 text-sm'},h('p',null,'Generated by ',h('a',{href:'https://github.com/AnEntrypoint/gm',class:'text-indigo-400 hover:text-indigo-300'},'gm'),' — convention-driven multi-platform plugin generator'));}
528
- applyDiff(document.body,[NavBar(),Hero(),FeaturesSection(),StateMachineSection(),HooksSection(),InstallSection(),AlsoAvailableSection(),Footer()]);
529
- </script>
530
- </body>
531
- </html>
80
+ .platform-cols{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-6);}
81
+ @media (max-width:720px){.platform-cols{grid-template-columns:1fr;}.feat-row,.phase-row,.receipt-row{grid-template-columns:1fr;gap:var(--space-1);}.receipt-row{grid-template-columns:48px 1fr;}}
82
+ .col-head{margin-bottom:var(--space-3);color:var(--fg-2);}
83
+ .idx-row{display:grid;grid-template-columns:24px 1fr auto;align-items:center;gap:var(--space-3);padding:var(--space-2) var(--space-3);border-top:1px solid var(--ink);color:var(--ink);text-decoration:none;transition:background var(--dur-snap) var(--ease);}
84
+ .idx-row:last-child{border-bottom:1px solid var(--ink);}
85
+ .idx-row:hover{background:var(--ink);color:var(--paper);text-decoration:none;}
86
+ .idx-row:hover .idx-tag{color:var(--paper);}
87
+ .idx-active{background:var(--acid);color:var(--ink);}
88
+ .idx-active:hover{background:var(--acid);color:var(--ink);}
89
+ .idx-mark{font-family:var(--ff-mono);color:var(--fg-3);}
90
+ .idx-label{font-family:var(--ff-mono);text-transform:uppercase;letter-spacing:var(--tr-label);font-size:var(--fs-body);}
91
+ .idx-tag{font-family:var(--ff-mono);}
92
+
93
+ .app-foot{margin-top:var(--space-8);padding:var(--space-5) var(--space-5) var(--space-7) var(--space-5);}
94
+ .foot-row{display:flex;justify-content:space-between;gap:var(--space-4);padding-top:var(--space-3);}
95
+ </style>
96
+ </head>
97
+ <body>
98
+ <header class="app-top">
99
+ <span class="brand">247420<span class="slash">/</span>gm<span class="slash">/</span>copilot cli</span>
100
+ <nav>
101
+ <a href="https://anentrypoint.github.io/gm">← all platforms</a>
102
+ <a href="https://github.com/AnEntrypoint/gm-copilot-cli">source ↗</a>
103
+ </nav>
104
+ </header>
105
+ <div class="dateline">
106
+ <span class="t-micro">247420 / anentrypoint</span>
107
+ <span class="t-micro">Copilot CLI</span>
108
+ <span class="t-micro">v2.0.539</span>
109
+ <span class="t-micro">2026-04-21</span>
110
+ <span class="t-micro">probably emerging 🌀</span>
111
+ </div>
112
+ <main class="page">
113
+ <section class="hero">
114
+ <span class="stamp ink">cli tool</span>
115
+ <h1 class="t-hero">gm <span class="slash">/</span> copilot cli</h1>
116
+ <p class="t-prose lede">State machine agent with hooks, skills, and automated git enforcement</p>
117
+ <div class="hero-cta">
118
+ <a class="btn-stamp" href="https://github.com/AnEntrypoint/gm-copilot-cli">source ↗</a>
119
+ </div>
120
+ </section>
121
+ <section class="section">
122
+ <div class="section-head"><span class="t-label">§ install</span><hr class="rule"/></div>
123
+ <div class="receipt"><div class="receipt-row"><span class="t-label num">01</span><div class="receipt-body"><p class="t-body">install via GitHub CLI</p><pre class="receipt-cmd"><code>gh extension install AnEntrypoint/gm-copilot-cli</code></pre></div></div>
124
+ <div class="receipt-row"><span class="t-label num">02</span><div class="receipt-body"><p class="t-body">restart your terminal — activates automatically</p></div></div></div>
125
+ </section>
126
+ <section class="section">
127
+ <div class="section-head"><span class="t-label">§ features</span><hr class="rule"/></div>
128
+ <ul class="feat-list"><li class="feat-row"><span class="t-label feat-tag">state machine</span><span class="t-body feat-desc">immutable PLAN→EXECUTE→EMIT→VERIFY→COMPLETE phases with full mutable tracking</span></li>
129
+ <li class="feat-row"><span class="t-label feat-tag">semantic search</span><span class="t-body feat-desc">natural language codebase exploration via codesearch skill — no grep needed</span></li>
130
+ <li class="feat-row"><span class="t-label feat-tag">hooks</span><span class="t-body feat-desc">pre-tool, session-start, prompt-submit, and stop hooks for full lifecycle control</span></li>
131
+ <li class="feat-row"><span class="t-label feat-tag">agents</span><span class="t-body feat-desc">gm, codesearch, and websearch agents pre-configured and ready to use</span></li>
132
+ <li class="feat-row"><span class="t-label feat-tag">mcp integration</span><span class="t-body feat-desc">model context protocol server support built in</span></li>
133
+ <li class="feat-row"><span class="t-label feat-tag">auto-recovery</span><span class="t-body feat-desc">supervisor hierarchy ensures the system never crashes</span></li></ul>
134
+ </section>
135
+ <section class="section">
136
+ <div class="section-head"><span class="t-label">§ state machine</span><hr class="rule"/></div>
137
+ <p class="t-prose section-lede">every task follows the same five-phase cycle — no skipping, no shortcuts.</p>
138
+ <ol class="phase-list"><li class="phase-row"><span class="t-label phase-name">01 plan</span><span class="t-body phase-desc">write .gm/prd.yml with every unknown named before any work begins</span></li>
139
+ <li class="phase-row"><span class="t-label phase-name">02 execute</span><span class="t-body phase-desc">prove every hypothesis via witnessed execution, import real modules</span></li>
140
+ <li class="phase-row"><span class="t-label phase-name">03 emit</span><span class="t-body phase-desc">write files only after all tests pass — pre- and post-emit gates</span></li>
141
+ <li class="phase-row"><span class="t-label phase-name">04 verify</span><span class="t-body phase-desc">end-to-end execution confirms all changes work in real context</span></li>
142
+ <li class="phase-row"><span class="t-label phase-name">05 complete</span><span class="t-body phase-desc">.prd empty, git clean, all output pushed</span></li></ol>
143
+ </section>
144
+ <section class="section">
145
+ <div class="section-head"><span class="t-label">§ also available</span><hr class="rule"/></div>
146
+ <div class="platform-cols">
147
+ <div class="platform-col">
148
+ <p class="t-label col-head">cli tools</p>
149
+ <div class="idx-list"><a class="idx-row" href="https://anentrypoint.github.io/gm-cc"><span class="idx-mark">›</span><span class="idx-label">claude code</span><span class="idx-tag t-meta">gm-cc</span></a>
150
+ <a class="idx-row" href="https://anentrypoint.github.io/gm-gc"><span class="idx-mark">›</span><span class="idx-label">gemini cli</span><span class="idx-tag t-meta">gm-gc</span></a>
151
+ <a class="idx-row" href="https://anentrypoint.github.io/gm-oc"><span class="idx-mark">›</span><span class="idx-label">opencode</span><span class="idx-tag t-meta">gm-oc</span></a>
152
+ <a class="idx-row" href="https://anentrypoint.github.io/gm-kilo"><span class="idx-mark">›</span><span class="idx-label">kilo code</span><span class="idx-tag t-meta">gm-kilo</span></a>
153
+ <a class="idx-row" href="https://anentrypoint.github.io/gm-codex"><span class="idx-mark">›</span><span class="idx-label">codex</span><span class="idx-tag t-meta">gm-codex</span></a>
154
+ <a class="idx-row idx-active" href="#"><span class="idx-mark">◆</span><span class="idx-label">copilot cli</span><span class="idx-tag t-meta">gm-copilot-cli</span></a>
155
+ <a class="idx-row" href="https://anentrypoint.github.io/gm-qwen"><span class="idx-mark">›</span><span class="idx-label">qwen code</span><span class="idx-tag t-meta">gm-qwen</span></a>
156
+ <a class="idx-row" href="https://anentrypoint.github.io/gm-hermes"><span class="idx-mark">›</span><span class="idx-label">hermes agent</span><span class="idx-tag t-meta">gm-hermes</span></a></div>
157
+ </div>
158
+ <div class="platform-col">
159
+ <p class="t-label col-head">ide extensions</p>
160
+ <div class="idx-list"><a class="idx-row" href="https://anentrypoint.github.io/gm-vscode"><span class="idx-mark">›</span><span class="idx-label">vs code</span><span class="idx-tag t-meta">gm-vscode</span></a>
161
+ <a class="idx-row" href="https://anentrypoint.github.io/gm-cursor"><span class="idx-mark">›</span><span class="idx-label">cursor</span><span class="idx-tag t-meta">gm-cursor</span></a>
162
+ <a class="idx-row" href="https://anentrypoint.github.io/gm-zed"><span class="idx-mark">›</span><span class="idx-label">zed</span><span class="idx-tag t-meta">gm-zed</span></a>
163
+ <a class="idx-row" href="https://anentrypoint.github.io/gm-jetbrains"><span class="idx-mark">›</span><span class="idx-label">jetbrains</span><span class="idx-tag t-meta">gm-jetbrains</span></a></div>
164
+ </div>
165
+ </div>
166
+ </section>
167
+ </main>
168
+ <footer class="app-foot">
169
+ <hr class="rule-double"/>
170
+ <div class="foot-row">
171
+ <span class="t-micro">generated by gm — convention-driven multi-platform plugin generator</span>
172
+ <span class="t-micro">probably emerging 🌀</span>
173
+ </div>
174
+ </footer>
175
+ </body></html>
package/manifest.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  name: gm
2
- version: 2.0.537
2
+ version: 2.0.539
3
3
  description: State machine agent with hooks, skills, and automated git enforcement
4
4
  author: AnEntrypoint
5
5
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-copilot-cli",
3
- "version": "2.0.537",
3
+ "version": "2.0.539",
4
4
  "description": "State machine agent with hooks, skills, and automated git enforcement",
5
5
  "author": "AnEntrypoint",
6
6
  "license": "MIT",
package/tools.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm",
3
- "version": "2.0.537",
3
+ "version": "2.0.539",
4
4
  "description": "State machine agent with hooks, skills, and automated git enforcement",
5
5
  "tools": [
6
6
  {