@staix/agent-hub 0.12.44 → 0.12.45

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 (137) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +3 -3
  3. package/THIRD_PARTY_NOTICES.md +29 -0
  4. package/docs/adding-an-ai-tool.md +102 -14
  5. package/docs/agent-notes/README.md +9 -0
  6. package/docs/agent-notes/adapters.md +58 -44
  7. package/docs/agent-notes/budget.md +1 -1
  8. package/docs/agent-notes/daemon.md +9 -7
  9. package/docs/agent-notes/local-worker.md +4 -3
  10. package/docs/agent-notes/tasks.md +8 -5
  11. package/docs/agent-notes/tests.md +7 -7
  12. package/docs/operations.md +99 -7
  13. package/docs/quickstart.md +5 -1
  14. package/docs/sdlc.md +26 -8
  15. package/docs/security.md +6 -3
  16. package/docs/specs/2026-09-19-agent-hub-design.md +114 -5
  17. package/docs/verification/2026-10-21-469-r1-dashboard-tokens.md +43 -0
  18. package/docs/verification/2026-10-21-469-r2-dashboard-shell.md +54 -0
  19. package/docs/verification/2026-10-21-469-r3-dashboard-board.md +51 -0
  20. package/docs/verification/2026-10-21-469-r4-dashboard-views.md +77 -0
  21. package/docs/verification/2026-10-21-469-r6-dashboard-motion-states.md +82 -0
  22. package/docs/verification/2026-10-22-0.12.45.md +60 -0
  23. package/docs/verification/assets/469-r1-board-1440-dark.png +0 -0
  24. package/docs/verification/assets/469-r1-board-1440-light.png +0 -0
  25. package/docs/verification/assets/469-r1-board-390-dark.png +0 -0
  26. package/docs/verification/assets/469-r1-board-390-light.png +0 -0
  27. package/docs/verification/assets/469-r2-agents-1440-dark.png +0 -0
  28. package/docs/verification/assets/469-r2-agents-768-dark.png +0 -0
  29. package/docs/verification/assets/469-r2-board-1024-light.png +0 -0
  30. package/docs/verification/assets/469-r2-board-1440-dark.png +0 -0
  31. package/docs/verification/assets/469-r2-board-1440-light.png +0 -0
  32. package/docs/verification/assets/469-r2-board-390-dark.png +0 -0
  33. package/docs/verification/assets/469-r2-board-390-light.png +0 -0
  34. package/docs/verification/assets/469-r2-board-768-light.png +0 -0
  35. package/docs/verification/assets/469-r3-board-1440-dark.png +0 -0
  36. package/docs/verification/assets/469-r3-board-1440-light.png +0 -0
  37. package/docs/verification/assets/469-r3-board-390-light.png +0 -0
  38. package/docs/verification/assets/469-r3-detail-1440-dark.png +0 -0
  39. package/docs/verification/assets/469-r3-detail-1440-light.png +0 -0
  40. package/docs/verification/assets/469-r3-detail-390-dark.png +0 -0
  41. package/docs/verification/assets/469-r3-plan-1440-light.png +0 -0
  42. package/docs/verification/assets/469-r3-plan-390-light.png +0 -0
  43. package/docs/verification/assets/469-r4-agents-1440-dark.png +0 -0
  44. package/docs/verification/assets/469-r4-agents-1440-light.png +0 -0
  45. package/docs/verification/assets/469-r4-agents-390-dark.png +0 -0
  46. package/docs/verification/assets/469-r4-memory-1440-dark.png +0 -0
  47. package/docs/verification/assets/469-r4-memory-1440-light.png +0 -0
  48. package/docs/verification/assets/469-r4-memory-390-dark.png +0 -0
  49. package/docs/verification/assets/469-r4-message-1440-light.png +0 -0
  50. package/docs/verification/assets/469-r4-office-1440-dark.png +0 -0
  51. package/docs/verification/assets/469-r4-office-1440-light.png +0 -0
  52. package/docs/verification/assets/469-r4-settings-1440-dark.png +0 -0
  53. package/docs/verification/assets/469-r4-settings-1440-light.png +0 -0
  54. package/docs/verification/assets/469-r4-stream-1440-light.png +0 -0
  55. package/docs/verification/assets/469-r4-stream-390-light.png +0 -0
  56. package/docs/verification/assets/469-r6-agents-empty-390-dark.png +0 -0
  57. package/docs/verification/assets/469-r6-agents-empty-390-light.png +0 -0
  58. package/docs/verification/assets/469-r6-board-1440-light.png +0 -0
  59. package/docs/verification/assets/469-r6-board-390-dark.png +0 -0
  60. package/docs/verification/assets/469-r6-board-empty-1440-dark.png +0 -0
  61. package/docs/verification/assets/469-r6-board-empty-1440-light.png +0 -0
  62. package/docs/verification/assets/469-r6-disconnected-1440-dark.png +0 -0
  63. package/docs/verification/assets/469-r6-disconnected-1440-light.png +0 -0
  64. package/docs/verification/assets/469-r6-disconnected-390-dark.png +0 -0
  65. package/docs/verification/assets/469-r6-skeleton-1440-light.png +0 -0
  66. package/docs/verification/assets/469-r6-skeleton-390-dark.png +0 -0
  67. package/docs/verification/assets/469-r6-toasts-1440-dark.png +0 -0
  68. package/docs/verification/assets/469-r6-toasts-1440-light.png +0 -0
  69. package/docs/verification/assets/469-r6-toasts-390-light.png +0 -0
  70. package/docs/verified.json +19 -16
  71. package/package.json +5 -1
  72. package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
  73. package/plugins/agent-hub/server.js +9818 -9605
  74. package/src/adapters/adapter-api.ts +2 -0
  75. package/src/adapters/agy/definition.ts +3 -1
  76. package/src/adapters/claude-channel.ts +14 -5
  77. package/src/adapters/codex-appserver.ts +1 -0
  78. package/src/adapters/conformance/acp.ts +114 -0
  79. package/src/adapters/conformance/codex.ts +191 -0
  80. package/src/adapters/conformance/enrollment.ts +43 -0
  81. package/src/adapters/conformance/factories.ts +17 -0
  82. package/src/adapters/conformance/fake-paths.ts +12 -0
  83. package/src/adapters/conformance/fakes/acp-server.ts +267 -0
  84. package/src/adapters/conformance/fakes/acp-watchdog-agent.ts +10 -0
  85. package/src/adapters/conformance/fakes/app-server.ts +119 -0
  86. package/src/adapters/conformance/fakes/codex-bin.ts +15 -0
  87. package/src/adapters/conformance/fakes/jcode-agent.ts +91 -0
  88. package/src/adapters/conformance/fakes/model-server.ts +39 -0
  89. package/src/adapters/conformance/fakes/pi-rpc.ts +32 -0
  90. package/src/adapters/conformance/index.ts +11 -0
  91. package/src/adapters/conformance/kit.ts +50 -0
  92. package/src/adapters/conformance/local-pi.ts +100 -0
  93. package/src/adapters/conformance/owned-acp.ts +44 -0
  94. package/src/adapters/definitions/builtin-metadata.ts +23 -6
  95. package/src/adapters/definitions/native-cli-entry-kimi.ts +7 -1
  96. package/src/adapters/definitions/native-cli-entry.ts +7 -19
  97. package/src/adapters/definitions/native-cli-preview.ts +2 -11
  98. package/src/adapters/definitions/qwen.ts +4 -1
  99. package/src/adapters/external-metadata.ts +48 -0
  100. package/src/adapters/external-module-scan.ts +126 -0
  101. package/src/adapters/external-modules.ts +240 -0
  102. package/src/adapters/pi.ts +2 -0
  103. package/src/adapters/public.ts +7 -0
  104. package/src/adapters/registry-types.ts +10 -0
  105. package/src/adapters/registry.ts +51 -15
  106. package/src/cli/help.ts +21 -16
  107. package/src/cli/identity.ts +1 -1
  108. package/src/cli/main.ts +23 -5
  109. package/src/cli/upgrade-labels.ts +1 -1
  110. package/src/cli/upgrade-presentation.ts +1 -1
  111. package/src/cli/upgrade-restore-state.ts +3 -2
  112. package/src/cli/upgrade-runtime.ts +4 -1
  113. package/src/hub/board.ts +30 -4
  114. package/src/hub/config-apply.ts +18 -10
  115. package/src/hub/config-reload.ts +8 -5
  116. package/src/hub/config-trust.ts +1 -1
  117. package/src/hub/control-client.ts +4 -1
  118. package/src/hub/daemon.ts +95 -39
  119. package/src/hub/facts.ts +76 -13
  120. package/src/hub/hub-tools.ts +21 -5
  121. package/src/hub/instance-config.ts +17 -5
  122. package/src/hub/instance-execution.ts +20 -8
  123. package/src/hub/instances.ts +2 -1
  124. package/src/hub/peers.ts +9 -0
  125. package/src/hub/plan-conformance.ts +83 -0
  126. package/src/hub/review-findings.ts +104 -0
  127. package/src/hub/roster.ts +31 -5
  128. package/src/hub/sdlc-queue.ts +19 -4
  129. package/src/hub/sdlc-release.ts +16 -1
  130. package/src/hub/sdlc.ts +27 -12
  131. package/src/hub/settings.ts +5 -1
  132. package/src/hub/snapshots.ts +8 -6
  133. package/src/hub/tasks.ts +275 -45
  134. package/src/hub/ui.ts +2 -2
  135. package/src/ui/index.html +559 -78
  136. package/src/ui/office-model.ts +3 -1
  137. package/src/ui/peer-palette.ts +44 -0
@@ -182,7 +182,9 @@ export interface OfficeScene {
182
182
  export function officeModel(snapshot: OfficeSnapshotInput, previous: OfficeScene | null, options: { cols?: number; now?: number }): OfficeScene {
183
183
  const FIXED = OFFICE_PEER_ORDER;
184
184
  const KNOWN = ["proposed", "in_progress", "in_review", "changes_requested", "approved", "cancelled"];
185
- const GLYPHS: Record<string, string> = { idle: "○", busy: "●", offline: "×", paused: "‖", waiting: "⚑", unknown: "?" };
185
+ // Shape names, not text glyphs (#469 R4): the page paints each condition as an outline shape (officeGlyphNode) and only an unknown
186
+ // condition falls back to the text mark. The words come from LABELS, so a state is never carried by a symbol alone.
187
+ const GLYPHS: Record<string, string> = { idle: "ring", busy: "disc", offline: "cross", paused: "bars", waiting: "hand", unknown: "?" };
186
188
  const LABELS: Record<string, string> = { idle: "idle", busy: "busy", offline: "offline", paused: "paused", waiting: "waiting on approval" };
187
189
  const DESK_CAP = 12, ROOM_CARDS = 8, DESK_CARDS = 3;
188
190
  const DESK_W = 10, DESK_H = 20, DESK_DX = 12, DESK_DY = 22, DESK_COLS = 4, DESK_TOP = 3;
@@ -24,3 +24,47 @@ export function peerStyle(peer: string): (typeof PEER_PALETTE)[keyof typeof PEER
24
24
  export function peerPaletteCss(): string {
25
25
  return Object.entries(PEER_PALETTE).map(([key, value]) => `.peer-${key}{--peer-color:${value.css}}`).join("");
26
26
  }
27
+
28
+ // #469 R1: a light and a dark variant of every peer colour, one hue. The surfaces are the dashboard's panel tokens in
29
+ // src/ui/index.html (a test compares them); a colour is moved along lightness only until it reaches 3:1 on all of them.
30
+ export const LIGHT_SURFACES = Object.freeze(["#eeeef1", "#f8f8fa", "#fcfcfd", "#f1f1f4"] as const);
31
+ export const DARK_SURFACES = Object.freeze(["#121316", "#1a1b1f", "#222328", "#16171a"] as const);
32
+ const channel = (hex: string, at: number) => parseInt(hex.slice(at, at + 2), 16) / 255;
33
+ function luminance(hex: string): number {
34
+ const [r, g, b] = [1, 3, 5].map(at => channel(hex, at)).map(v => v <= 0.04045 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4);
35
+ return r! * 0.2126 + g! * 0.7152 + b! * 0.0722;
36
+ }
37
+ export function contrast(a: string, b: string): number {
38
+ const x = luminance(a), y = luminance(b);
39
+ return (Math.max(x, y) + 0.05) / (Math.min(x, y) + 0.05);
40
+ }
41
+ function toHsl(hex: string): [number, number, number] {
42
+ const [r, g, b] = [1, 3, 5].map(at => channel(hex, at)) as [number, number, number];
43
+ const max = Math.max(r, g, b), min = Math.min(r, g, b), l = (max + min) / 2, d = max - min;
44
+ if (d === 0) return [0, 0, l];
45
+ const s = d / (1 - Math.abs(2 * l - 1));
46
+ const h = max === r ? ((g - b) / d) % 6 : max === g ? (b - r) / d + 2 : (r - g) / d + 4;
47
+ return [(h * 60 + 360) % 360, s, l];
48
+ }
49
+ function fromHsl(h: number, s: number, l: number): string {
50
+ const c = (1 - Math.abs(2 * l - 1)) * s, x = c * (1 - Math.abs((h / 60) % 2 - 1)), m = l - c / 2;
51
+ const [r, g, b] = h < 60 ? [c, x, 0] : h < 120 ? [x, c, 0] : h < 180 ? [0, c, x] : h < 240 ? [0, x, c] : h < 300 ? [x, 0, c] : [c, 0, x];
52
+ return "#" + [r, g, b].map(v => Math.round((v + m) * 255).toString(16).padStart(2, "0")).join("");
53
+ }
54
+ /** The colour with the same hue and saturation, moved in lightness (darker on light surfaces, lighter on dark) until it clears 3:1 on every surface. */
55
+ export function peerVariant(css: string, theme: "light" | "dark"): string {
56
+ const surfaces = theme === "light" ? LIGHT_SURFACES : DARK_SURFACES;
57
+ const ok = (hex: string) => surfaces.every(surface => contrast(hex, surface) >= 3);
58
+ if (ok(css)) return css;
59
+ const [h, s, l] = toHsl(css), step = theme === "light" ? -0.005 : 0.005;
60
+ for (let next = l + step; next > 0 && next < 1; next += step) { const hex = fromHsl(h, s, next); if (ok(hex)) return hex; }
61
+ return css;
62
+ }
63
+ /** Per-theme peer colours: the light variant by default, the dark one under data-theme="dark" and under the system preference. */
64
+ export function peerPaletteThemeCss(): string {
65
+ const entries = Object.entries(PEER_PALETTE);
66
+ const rules = (theme: "light" | "dark", scope = "") => entries.map(([key, value]) => `${scope}${scope ? " " : ""}.peer-${key}{--peer-color:${peerVariant(value.css, theme)}}`).join("");
67
+ return rules("light")
68
+ + rules("dark", ':root[data-theme="dark"]')
69
+ + `@media(prefers-color-scheme:dark){${rules("dark", ':root:not([data-theme="light"]):not([data-theme="dark"])')}}`;
70
+ }