@starlove/orbit 1.1.1 → 1.1.11
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.
- package/.dockerignore +0 -0
- package/Dockerfile +0 -0
- package/LICENSE +0 -0
- package/README.md +2 -2
- package/SKILL-ORBIT.md +2 -0
- package/build.mjs +0 -0
- package/dist/full/apple-touch-icon.png +0 -0
- package/dist/full/cursors/live_arrow.cur +0 -0
- package/dist/full/cursors/live_link.cur +0 -0
- package/dist/full/cursors/live_move.cur +0 -0
- package/dist/full/cursors/live_select.cur +0 -0
- package/dist/full/cursors/live_unavail.cur +0 -0
- package/dist/full/favicon-32x32.png +0 -0
- package/dist/full/index.html +160 -15
- package/dist/full/js/app.55b38e12.js +698 -0
- package/dist/full/js/app.55b38e12.js.map +7 -0
- package/dist/full/orbits-favicon.png +0 -0
- package/dist/full/orbits-logo-bg.png +0 -0
- package/dist/full/orbits-logo.png +0 -0
- package/dist/full/{styles.836872e7.css → styles.273fc37a.css} +79 -39
- package/dist/full/version.json +2 -2
- package/docs/AGENT_PROTOCOL.md +22 -6
- package/docs/MCP_SETUP.md +0 -0
- package/docs/ORBIT_DISPATCH.md +68 -8
- package/docs/SS-Orbit-Dark.png +0 -0
- package/docs/SS-Orbit-Light.png +0 -0
- package/docs/mcp-client.example.json +0 -0
- package/docs/setup/orbit-init-wizard.md +0 -0
- package/package.json +1 -1
- package/public/apple-touch-icon.png +0 -0
- package/public/cursors/live_arrow.cur +0 -0
- package/public/cursors/live_link.cur +0 -0
- package/public/cursors/live_move.cur +0 -0
- package/public/cursors/live_select.cur +0 -0
- package/public/cursors/live_unavail.cur +0 -0
- package/public/favicon-32x32.png +0 -0
- package/public/index.html +158 -13
- package/public/js/actor-labels.js +0 -0
- package/public/js/api.js +0 -0
- package/public/js/app.js +0 -0
- package/public/js/board-menu.js +0 -0
- package/public/js/card-actions.js +19 -0
- package/public/js/config.js +0 -0
- package/public/js/create-card.js +0 -0
- package/public/js/dom.js +0 -0
- package/public/js/drawer.js +17 -43
- package/public/js/format.js +5 -5
- package/public/js/kanban.js +157 -92
- package/public/js/local-backend.js +15 -4
- package/public/js/main.js +2 -1
- package/public/js/modal.js +0 -0
- package/public/js/motion-preference.js +14 -3
- package/public/js/router.js +0 -0
- package/public/js/search.js +0 -0
- package/public/js/settings-tabs.js +0 -0
- package/public/js/settings.js +131 -27
- package/public/js/sse.js +0 -0
- package/public/js/starscape.js +0 -0
- package/public/js/state.js +0 -0
- package/public/js/theme-preference.js +0 -0
- package/public/js/ticket-detail.js +88 -20
- package/public/js/toast.js +0 -0
- package/public/js/transport.js +0 -0
- package/public/js/unread.js +0 -0
- package/public/js/url-routes.js +0 -0
- package/public/orbits-favicon.png +0 -0
- package/public/orbits-logo-bg.png +0 -0
- package/public/orbits-logo.png +0 -0
- package/public/styles.css +79 -39
- package/src/cli/orbit.js +22 -0
- package/src/core/agent.js +25 -4
- package/src/core/agents-md.js +0 -0
- package/src/core/attachments.js +0 -0
- package/src/core/auth.js +0 -0
- package/src/core/backups.js +0 -0
- package/src/core/board.js +2 -1
- package/src/core/boards.js +0 -0
- package/src/core/bootstrap.js +0 -0
- package/src/core/db.js +19 -0
- package/src/core/delete-board.js +0 -0
- package/src/core/dispatch.js +178 -13
- package/src/core/events.js +0 -0
- package/src/core/http.js +0 -0
- package/src/core/migrate.js +0 -0
- package/src/core/paths.js +0 -0
- package/src/core/provision-repo-board.js +0 -0
- package/src/core/queries.js +0 -0
- package/src/core/registry.js +2 -2
- package/src/core/relations.js +0 -0
- package/src/core/review-verdicts.js +138 -0
- package/src/core/router.js +38 -3
- package/src/core/search.js +0 -0
- package/src/core/seed.js +0 -0
- package/src/core/snapshots.js +429 -9
- package/src/core/states.js +0 -0
- package/src/core/system-picker.js +0 -0
- package/src/core/tickets.js +0 -0
- package/src/core/util.js +0 -0
- package/src/mcp/orbit-client.js +47 -19
- package/src/mcp-server.js +122 -26
- package/src/server.js +0 -0
- package/dist/full/js/app.a4f045fc.js +0 -676
- package/dist/full/js/app.a4f045fc.js.map +0 -7
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -321,7 +321,7 @@ textarea:focus {
|
|
|
321
321
|
}
|
|
322
322
|
|
|
323
323
|
@media (prefers-reduced-motion: reduce) {
|
|
324
|
-
[data-theme="dark"] .topbar {
|
|
324
|
+
:root:not([data-motion="full"])[data-theme="dark"] .topbar {
|
|
325
325
|
transition: none;
|
|
326
326
|
}
|
|
327
327
|
}
|
|
@@ -1037,8 +1037,8 @@ h1 {
|
|
|
1037
1037
|
}
|
|
1038
1038
|
|
|
1039
1039
|
@media (prefers-reduced-motion: reduce) {
|
|
1040
|
-
.create-flyout,
|
|
1041
|
-
.create-flyout-backdrop {
|
|
1040
|
+
:root:not([data-motion="full"]) .create-flyout,
|
|
1041
|
+
:root:not([data-motion="full"]) .create-flyout-backdrop {
|
|
1042
1042
|
transition: none;
|
|
1043
1043
|
}
|
|
1044
1044
|
}
|
|
@@ -1347,7 +1347,7 @@ h1 {
|
|
|
1347
1347
|
}
|
|
1348
1348
|
|
|
1349
1349
|
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: reduce) {
|
|
1350
|
-
.add-card-phantom {
|
|
1350
|
+
:root:not([data-motion="full"]) .add-card-phantom {
|
|
1351
1351
|
transition:
|
|
1352
1352
|
color 160ms ease,
|
|
1353
1353
|
border-color 160ms ease,
|
|
@@ -1402,7 +1402,7 @@ h1 {
|
|
|
1402
1402
|
}
|
|
1403
1403
|
|
|
1404
1404
|
@media (prefers-reduced-motion: reduce) {
|
|
1405
|
-
.agent-dot {
|
|
1405
|
+
:root:not([data-motion="full"]) .agent-dot {
|
|
1406
1406
|
animation: none;
|
|
1407
1407
|
}
|
|
1408
1408
|
}
|
|
@@ -1443,7 +1443,7 @@ h1 {
|
|
|
1443
1443
|
}
|
|
1444
1444
|
|
|
1445
1445
|
@media (prefers-reduced-motion: reduce) {
|
|
1446
|
-
.card-unread-dot {
|
|
1446
|
+
:root:not([data-motion="full"]) .card-unread-dot {
|
|
1447
1447
|
animation: none;
|
|
1448
1448
|
}
|
|
1449
1449
|
}
|
|
@@ -1691,7 +1691,7 @@ h1 {
|
|
|
1691
1691
|
}
|
|
1692
1692
|
|
|
1693
1693
|
@media (prefers-reduced-motion: reduce) {
|
|
1694
|
-
.card {
|
|
1694
|
+
:root:not([data-motion="full"]) .card {
|
|
1695
1695
|
animation: none;
|
|
1696
1696
|
}
|
|
1697
1697
|
}
|
|
@@ -1823,8 +1823,10 @@ h1 {
|
|
|
1823
1823
|
[data-theme="dark"] .card {
|
|
1824
1824
|
border-color: rgba(var(--starlight-rgb),0.12);
|
|
1825
1825
|
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.25);
|
|
1826
|
-
backdrop-filter: blur
|
|
1827
|
-
|
|
1826
|
+
/* No backdrop-filter: --card is 85% opaque so the blur showed through ~15%
|
|
1827
|
+
(near-invisible) yet forced every card to re-blur the animated starfield
|
|
1828
|
+
behind it on every frame — the page's biggest GPU cost. The opaque fill
|
|
1829
|
+
carries the surface; the starfield still animates in the gaps. */
|
|
1828
1830
|
}
|
|
1829
1831
|
|
|
1830
1832
|
[data-theme="dark"] .card.type-epic {
|
|
@@ -2134,7 +2136,7 @@ h1 {
|
|
|
2134
2136
|
}
|
|
2135
2137
|
|
|
2136
2138
|
@media (prefers-reduced-motion: reduce) {
|
|
2137
|
-
.priority-pill-urgent {
|
|
2139
|
+
:root:not([data-motion="full"]) .priority-pill-urgent {
|
|
2138
2140
|
animation: none;
|
|
2139
2141
|
}
|
|
2140
2142
|
}
|
|
@@ -2165,11 +2167,17 @@ h1 {
|
|
|
2165
2167
|
}
|
|
2166
2168
|
|
|
2167
2169
|
@media (prefers-reduced-motion: no-preference) {
|
|
2168
|
-
[data-theme="dark"] .priority-pill-urgent {
|
|
2170
|
+
:root:not([data-motion="reduce"])[data-theme="dark"] .priority-pill-urgent {
|
|
2169
2171
|
box-shadow: 0 0 0 1px rgba(var(--coral-rgb),0.35), 0 4px 10px rgba(var(--coral-rgb),0.3);
|
|
2170
2172
|
}
|
|
2171
2173
|
}
|
|
2172
2174
|
|
|
2175
|
+
/* Full-motion escape hatch: show the urgent glow even when the OS prefers
|
|
2176
|
+
reduced motion but the user forced full motion. */
|
|
2177
|
+
:root[data-motion="full"][data-theme="dark"] .priority-pill-urgent {
|
|
2178
|
+
box-shadow: 0 0 0 1px rgba(var(--coral-rgb),0.35), 0 4px 10px rgba(var(--coral-rgb),0.3);
|
|
2179
|
+
}
|
|
2180
|
+
|
|
2173
2181
|
.card-expand-trigger {
|
|
2174
2182
|
display: flex;
|
|
2175
2183
|
align-items: center;
|
|
@@ -2339,8 +2347,8 @@ h1 {
|
|
|
2339
2347
|
}
|
|
2340
2348
|
|
|
2341
2349
|
@media (prefers-reduced-motion: reduce) {
|
|
2342
|
-
.drawer,
|
|
2343
|
-
.drawer-backdrop {
|
|
2350
|
+
:root:not([data-motion="full"]) .drawer,
|
|
2351
|
+
:root:not([data-motion="full"]) .drawer-backdrop {
|
|
2344
2352
|
transition: none;
|
|
2345
2353
|
}
|
|
2346
2354
|
}
|
|
@@ -3671,16 +3679,13 @@ details.section > summary .mcp-title-row {
|
|
|
3671
3679
|
min-height: 2rem;
|
|
3672
3680
|
}
|
|
3673
3681
|
|
|
3674
|
-
/*
|
|
3675
|
-
|
|
3676
|
-
.settings-notes-body
|
|
3682
|
+
/* Long-form settings fields reserve textarea-sized landing areas so they don't
|
|
3683
|
+
collapse to one-liners when empty. */
|
|
3684
|
+
.settings-notes-body,
|
|
3685
|
+
.settings-agent-instructions-body {
|
|
3677
3686
|
min-height: 11rem;
|
|
3678
3687
|
}
|
|
3679
3688
|
|
|
3680
|
-
.ai-context-setup textarea[name="agent_instructions"] {
|
|
3681
|
-
min-height: 9rem;
|
|
3682
|
-
}
|
|
3683
|
-
|
|
3684
3689
|
.ai-context-setup > .description {
|
|
3685
3690
|
margin-bottom: 0.7rem;
|
|
3686
3691
|
}
|
|
@@ -5170,8 +5175,8 @@ button:disabled,
|
|
|
5170
5175
|
.toast-error .toast-icon { color: #ef4444; }
|
|
5171
5176
|
|
|
5172
5177
|
@media (prefers-reduced-motion: reduce) {
|
|
5173
|
-
.toast-enter { animation: none; opacity: 1; transform: none; }
|
|
5174
|
-
.toast-exit { animation: none; }
|
|
5178
|
+
:root:not([data-motion="full"]) .toast-enter { animation: none; opacity: 1; transform: none; }
|
|
5179
|
+
:root:not([data-motion="full"]) .toast-exit { animation: none; }
|
|
5175
5180
|
}
|
|
5176
5181
|
|
|
5177
5182
|
[data-theme="dark"] .toast {
|
|
@@ -5332,8 +5337,8 @@ button:disabled,
|
|
|
5332
5337
|
}
|
|
5333
5338
|
|
|
5334
5339
|
@media (prefers-reduced-motion: reduce) {
|
|
5335
|
-
.orbit-dialog,
|
|
5336
|
-
.orbit-dialog::backdrop {
|
|
5340
|
+
:root:not([data-motion="full"]) .orbit-dialog,
|
|
5341
|
+
:root:not([data-motion="full"]) .orbit-dialog::backdrop {
|
|
5337
5342
|
animation: none;
|
|
5338
5343
|
}
|
|
5339
5344
|
}
|
|
@@ -5669,40 +5674,75 @@ button:disabled,
|
|
|
5669
5674
|
}
|
|
5670
5675
|
}
|
|
5671
5676
|
|
|
5677
|
+
/* Reduced motion — Starscape v3 `data-motion` contract (migrated from the
|
|
5678
|
+
* legacy `data-reduced-motion="reduce|allow"`):
|
|
5679
|
+
* • OS path: reduce when the OS asks, unless the user forces full motion.
|
|
5680
|
+
* • Explicit path: `data-motion="reduce"` reduces regardless of OS.
|
|
5681
|
+
* • `data-motion="full"` opts out of the OS path (full motion even on OS reduce). */
|
|
5672
5682
|
@media (prefers-reduced-motion: reduce) {
|
|
5673
|
-
[data-
|
|
5674
|
-
[data-
|
|
5675
|
-
[data-
|
|
5676
|
-
|
|
5677
|
-
|
|
5683
|
+
:root:not([data-motion="full"]) *,
|
|
5684
|
+
:root:not([data-motion="full"]) *::before,
|
|
5685
|
+
:root:not([data-motion="full"]) *::after {
|
|
5686
|
+
scroll-behavior: auto !important;
|
|
5687
|
+
transition-duration: 0.01ms !important;
|
|
5688
|
+
animation-duration: 0.01ms !important;
|
|
5689
|
+
animation-iteration-count: 1 !important;
|
|
5690
|
+
}
|
|
5691
|
+
|
|
5692
|
+
:root:not([data-motion="full"])[data-theme="dark"] .starfield,
|
|
5693
|
+
:root:not([data-motion="full"])[data-theme="dark"] .milky-way,
|
|
5694
|
+
:root:not([data-motion="full"])[data-theme="dark"] .grain::before,
|
|
5695
|
+
:root:not([data-motion="full"])[data-theme="dark"] .grain::after,
|
|
5696
|
+
:root:not([data-motion="full"])[data-theme="dark"] .signature-star {
|
|
5678
5697
|
animation: none;
|
|
5679
5698
|
}
|
|
5680
|
-
|
|
5699
|
+
|
|
5700
|
+
:root:not([data-motion="full"])[data-theme="dark"] .meteor {
|
|
5681
5701
|
display: none;
|
|
5682
5702
|
}
|
|
5683
5703
|
}
|
|
5684
5704
|
|
|
5685
|
-
[data-
|
|
5686
|
-
[data-
|
|
5687
|
-
[data-
|
|
5705
|
+
[data-motion="reduce"] *,
|
|
5706
|
+
[data-motion="reduce"] *::before,
|
|
5707
|
+
[data-motion="reduce"] *::after {
|
|
5688
5708
|
scroll-behavior: auto !important;
|
|
5689
5709
|
transition-duration: 0.01ms !important;
|
|
5690
5710
|
animation-duration: 0.01ms !important;
|
|
5691
5711
|
animation-iteration-count: 1 !important;
|
|
5692
5712
|
}
|
|
5693
5713
|
|
|
5694
|
-
[data-
|
|
5695
|
-
[data-
|
|
5696
|
-
[data-
|
|
5697
|
-
[data-
|
|
5698
|
-
[data-
|
|
5714
|
+
[data-motion="reduce"][data-theme="dark"] .starfield,
|
|
5715
|
+
[data-motion="reduce"][data-theme="dark"] .milky-way,
|
|
5716
|
+
[data-motion="reduce"][data-theme="dark"] .grain::before,
|
|
5717
|
+
[data-motion="reduce"][data-theme="dark"] .grain::after,
|
|
5718
|
+
[data-motion="reduce"][data-theme="dark"] .signature-star {
|
|
5699
5719
|
animation: none;
|
|
5700
5720
|
}
|
|
5701
5721
|
|
|
5702
|
-
[data-
|
|
5722
|
+
[data-motion="reduce"][data-theme="dark"] .meteor {
|
|
5703
5723
|
display: none;
|
|
5704
5724
|
}
|
|
5705
5725
|
|
|
5726
|
+
/* Empty-lane icon micro-motion — a low-amplitude exception to the OS reduced-
|
|
5727
|
+
* motion reset above. These are small (64px), slow, localized loops, not the
|
|
5728
|
+
* large-area/parallax motion that triggers vestibular discomfort, so they
|
|
5729
|
+
* survive an *OS-level* reduced-motion preference. They are still fully stopped
|
|
5730
|
+
* by an *explicit* in-app choice (data-motion="reduce") — a deliberate "calm it
|
|
5731
|
+
* down" wins over the ambient OS default. The !important + selector specificity
|
|
5732
|
+
* is what overrides the universal `* { animation-duration: 0.01ms !important }`
|
|
5733
|
+
* reset for just these elements. */
|
|
5734
|
+
@media (prefers-reduced-motion: reduce) {
|
|
5735
|
+
:root:not([data-motion="reduce"]) .empty-state-icon.star {
|
|
5736
|
+
animation: star-pulse 4s ease-in-out infinite !important;
|
|
5737
|
+
}
|
|
5738
|
+
:root:not([data-motion="reduce"]) .empty-state-icon.ai-sparkle {
|
|
5739
|
+
animation: ai-float 6s ease-in-out infinite !important;
|
|
5740
|
+
}
|
|
5741
|
+
:root:not([data-motion="reduce"]) .empty-state-icon.orbit .satellite {
|
|
5742
|
+
animation: orbit-rotate 10s linear infinite !important;
|
|
5743
|
+
}
|
|
5744
|
+
}
|
|
5745
|
+
|
|
5706
5746
|
[data-theme="dark"] {
|
|
5707
5747
|
/* Tells the browser to render native widgets (dropdowns, scrollbars,
|
|
5708
5748
|
date pickers, etc.) in their dark variant so option popups match. */
|
package/dist/full/version.json
CHANGED
package/docs/AGENT_PROTOCOL.md
CHANGED
|
@@ -72,7 +72,7 @@ Returns the first schedulable `AI Ready` ticket. The scheduler skips tickets blo
|
|
|
72
72
|
|
|
73
73
|
By default, `claim-next` skips `epic` cards because they are index/planning cards. To claim an epic for planning, pass `"type": "epic"` or `"include_epics": true`.
|
|
74
74
|
|
|
75
|
-
The response shape is `{ claimed: true, ticket_id, context }` where `context` is the lightweight `board_read_ticket` pack (`ticket` with title/description/labels/state and the `board_manual`). Ticket comments are not included in the default claim context; call `GET /api/tickets/:id/comments` (or MCP `board_read_comments`) when an explicit chat/comment surface needs them. For the
|
|
75
|
+
The response shape is `{ claimed: true, ticket_id, context }` where `context` is the lightweight `board_read_ticket` pack (`ticket` with title/description/labels/state and the `board_manual`). Ticket comments are not included in the default claim context; call `GET /api/tickets/:id/comments` (or MCP `board_read_comments`) when an explicit chat/comment surface needs them. For the lean ticket relationship pack, call `GET /api/tickets/:id/context` (or MCP `board_get_ticket_context`). For the historical heavy pack with board manual/journal attached, call `GET /api/tickets/:id/context/full` (or MCP `board_get_ticket_context_full`).
|
|
76
76
|
|
|
77
77
|
### Read Lightweight Ticket
|
|
78
78
|
|
|
@@ -86,7 +86,7 @@ MCP equivalent: `board_read_ticket`.
|
|
|
86
86
|
|
|
87
87
|
Returns the lightweight agent read shape: `ticket` with identity, title, description, labels, state/type/priority, plus `board_manual`. Ticket comments, relations, blockers, child cards, and implementation fields are intentionally omitted. Use this for quick orientation and claim context. The `lookup` form is exact by per-board ticket number or exact title; it does not use fuzzy search or comment/implementation indexes.
|
|
88
88
|
|
|
89
|
-
### Get Context Pack
|
|
89
|
+
### Get Lean Ticket Context Pack
|
|
90
90
|
|
|
91
91
|
```http
|
|
92
92
|
GET /api/tickets/:id/context?depth=1
|
|
@@ -94,15 +94,31 @@ GET /api/tickets/:id/context?depth=1
|
|
|
94
94
|
|
|
95
95
|
Returns:
|
|
96
96
|
|
|
97
|
-
- Ticket, board, state, labels.
|
|
98
|
-
- The board manual (`board_manual`), including `agent_instructions` and `project_notes`.
|
|
97
|
+
- Ticket, board identity, state, labels.
|
|
99
98
|
- Dedicated implementation fields: `ai_plan`, `implementation_summary`, and `implementation_updates`.
|
|
100
99
|
- Parent epic/story ticket when present.
|
|
101
100
|
- Child feature cards when the ticket is an epic/story.
|
|
102
101
|
- Related tickets.
|
|
103
102
|
- Blockers and blocking tickets.
|
|
104
103
|
|
|
105
|
-
|
|
104
|
+
Project manual/journal (`agent_instructions`, `project_notes`, and board entries) and ticket comments are intentionally omitted from this default agent context. Fetch project context and comments explicitly when needed:
|
|
105
|
+
|
|
106
|
+
```http
|
|
107
|
+
GET /api/boards/:board_id/context?include_struck=false
|
|
108
|
+
GET /api/tickets/:id/comments
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
MCP equivalents: `board_context` and `board_read_comments`.
|
|
112
|
+
|
|
113
|
+
### Get Full Ticket Context Pack
|
|
114
|
+
|
|
115
|
+
```http
|
|
116
|
+
GET /api/tickets/:id/context/full?depth=1
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
MCP equivalent: `board_get_ticket_context_full`.
|
|
120
|
+
|
|
121
|
+
Returns the historical heavy context shape: everything in the lean ticket context plus the full board row and `board_manual` / journal. Comments are still intentionally omitted; explicit comment/chat consumers should call:
|
|
106
122
|
|
|
107
123
|
```http
|
|
108
124
|
GET /api/tickets/:id/comments
|
|
@@ -176,7 +192,7 @@ Searches ticket titles, descriptions, and comments.
|
|
|
176
192
|
GET /api/boards/:board_id/context?include_struck=false
|
|
177
193
|
```
|
|
178
194
|
|
|
179
|
-
Returns the same shape as MCP `board_context`:
|
|
195
|
+
Returns the same shape as MCP `board_context`: board metadata (`agent_instructions`, `project_notes`, repository paths, default branch), `entries` (journal / decisions / lessons), and `deployment` paths. Use `include_struck=true` to include struck journal rows (default off).
|
|
180
196
|
|
|
181
197
|
MCP: `board_context` with optional `board_id` / `board_slug` / `board` and optional `include_struck`.
|
|
182
198
|
|
package/docs/MCP_SETUP.md
CHANGED
|
File without changes
|
package/docs/ORBIT_DISPATCH.md
CHANGED
|
@@ -44,6 +44,11 @@ orbit dispatch --board my-app --ticket 12 --profile agent --worktree --foregroun
|
|
|
44
44
|
orbit dispatch --board my-app --ticket 12 --profile agent --worktree \
|
|
45
45
|
--branch orbit/my-app-12-search \
|
|
46
46
|
--worktree-path .worktrees/my-app-12-search
|
|
47
|
+
|
|
48
|
+
# Declare ticket-specific verification expectations in the handoff/run record.
|
|
49
|
+
orbit dispatch --board my-app --ticket 12 --profile agent --worktree \
|
|
50
|
+
--verify-command "node --test test/orbit-cli.test.mjs" \
|
|
51
|
+
--verify-command "git diff --check"
|
|
47
52
|
```
|
|
48
53
|
|
|
49
54
|
## Preflight order
|
|
@@ -55,8 +60,9 @@ Before any filesystem writes, worktree creation, ticket mutation, or agent spawn
|
|
|
55
60
|
3. Resolves the ticket from `--ticket` by number or id.
|
|
56
61
|
4. Refuses archived tickets.
|
|
57
62
|
5. Refuses blocked tickets unless `--force` is passed.
|
|
58
|
-
6.
|
|
59
|
-
7.
|
|
63
|
+
6. Rejects missing or flag-looking `--verify-command` values during CLI argument parsing.
|
|
64
|
+
7. For spawn mode, checks that the Hermes binary exists and the requested profile is plausible.
|
|
65
|
+
8. Handles `--dry-run` as a true no-write preview.
|
|
60
66
|
|
|
61
67
|
Only after those checks does dispatch create run artifacts/worktrees, write the handoff/comment, move the ticket, or spawn Hermes.
|
|
62
68
|
|
|
@@ -67,14 +73,65 @@ In normal spawn mode:
|
|
|
67
73
|
1. Builds a run id such as `orbit-12-agent-abc123def0`.
|
|
68
74
|
2. Creates `.orbit/dispatch-runs/<run-id>/` for run metadata and policy wrappers.
|
|
69
75
|
3. Creates and preserves a git worktree/branch when `--worktree` is used.
|
|
70
|
-
4. Generates a full agent handoff
|
|
71
|
-
5.
|
|
72
|
-
6.
|
|
73
|
-
7.
|
|
76
|
+
4. Generates a full agent handoff.
|
|
77
|
+
5. Writes an initial durable `run-record.json` with status `prepared` before ticket mutation or agent spawn.
|
|
78
|
+
6. Writes the canonical handoff copy to the ticket's **AI Written-Plan** (`ai_plan`) field.
|
|
79
|
+
7. Moves the ticket to **In Progress**.
|
|
80
|
+
8. Starts Hermes.
|
|
81
|
+
9. Updates `run-record.json` to status `launched` with the child process id.
|
|
82
|
+
10. Comments a run record back onto the ticket.
|
|
83
|
+
|
|
84
|
+
In `--no-spawn` mode, dispatch writes the handoff, initial `run-record.json`, and run-record comment but leaves the ticket in its current lane.
|
|
85
|
+
|
|
86
|
+
The run record includes profile, policy, ticket, branch, worktree, base commit, policy-bin path, child process id, command, declared verification commands, mode, and a `run-record.json` path. This makes the card the visible cockpit for the run while preserving a machine-readable artifact for later review/repair automation.
|
|
87
|
+
|
|
88
|
+
## Structured run record
|
|
89
|
+
|
|
90
|
+
Every non-dry-run dispatch writes `<DATA_DIR>/dispatch-runs/<board>/<run-id>/run-record.json` with schema `orbit.dispatch.run.v1`.
|
|
91
|
+
|
|
92
|
+
The JSON record currently captures:
|
|
93
|
+
|
|
94
|
+
- run id, board id/slug, ticket id/number, profile, policy, mode, and status (`prepared` for `--no-spawn`, `launched` for spawned runs)
|
|
95
|
+
- prompt/handoff path, repo root, worktree, branch, and base commit
|
|
96
|
+
- process id when a Hermes child was spawned
|
|
97
|
+
- declared verification commands
|
|
98
|
+
- empty `commit_shas` and `residual_risks` arrays for completion/review tooling to fill in later slices
|
|
99
|
+
- a small environment-variance snapshot: platform, Node version, cwd, path format, and relevant `HOME`, `PROJECT_ROOT`, `DATA_DIR`, and `ORBIT_*` env vars
|
|
100
|
+
|
|
101
|
+
URL-bearing values are presence-only redacted in `run-record.json`. `ORBIT_API_URL`, `ORBIT_SERVER_URL`, and the top-level `server_url` field are recorded as `[redacted-url-present]` when present, rather than persisting usernames, passwords, query tokens, fragments, hostnames, or paths. Non-URL environment checklist values such as `HOME`, `PROJECT_ROOT`, `DATA_DIR`, `ORBIT_MODE`, and `ORBIT_DEFAULT_BOARD` remain visible for variance debugging.
|
|
102
|
+
|
|
103
|
+
Operators can override the default verification contract by repeating `--verify-command <cmd>` or using `--verify-command=<cmd>`. Bare `--verify-command`, `--verify-command=` and `--verify-command` followed by another flag are rejected before dispatch side effects. If omitted, dispatch declares the standard local-safe checklist: `npm test`, conditional `npm run build`, `node src/cli/orbit.js dispatch --help`, `git diff --check`, and `git diff --cached --check before commit`.
|
|
104
|
+
|
|
105
|
+
## Structured review verdict records
|
|
74
106
|
|
|
75
|
-
|
|
107
|
+
Sentinel/agent review results are first-class board data in `review_verdicts`, not prose-only comments. Each record belongs to one ticket and stores:
|
|
76
108
|
|
|
77
|
-
|
|
109
|
+
- `verdict`: one of `PASS`, `BLOCK`, or `QUESTION`
|
|
110
|
+
- `blocking_findings`: JSON array for issues that must be repaired before approval
|
|
111
|
+
- `optional_findings`: JSON array for non-blocking review notes
|
|
112
|
+
- `evidence_commands`: JSON array of commands or probes the reviewer used as evidence
|
|
113
|
+
- `reviewer_profile` and `reviewer_session_id`: optional reviewer identity/session metadata
|
|
114
|
+
- `reviewed_commit_sha`: optional commit SHA under review
|
|
115
|
+
- `dispatch_run_id`: optional dispatch run id tying the verdict back to `run-record.json`
|
|
116
|
+
- `supersedes_prior_review_id`: optional link to an earlier verdict on the same ticket
|
|
117
|
+
|
|
118
|
+
HTTP API:
|
|
119
|
+
|
|
120
|
+
```text
|
|
121
|
+
POST /api/tickets/:ticket_id/review-verdicts
|
|
122
|
+
GET /api/tickets/:ticket_id/review-verdicts?limit=50
|
|
123
|
+
GET /api/review-verdicts/:review_id?board=<slug-or-id>
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
MCP tools:
|
|
127
|
+
|
|
128
|
+
```text
|
|
129
|
+
board_create_review_verdict
|
|
130
|
+
board_list_review_verdicts
|
|
131
|
+
board_get_review_verdict
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Comments may mirror verdict summaries for human scanning, but comments are not the source of truth for review automation. Later repair and re-review tooling should read these records directly.
|
|
78
135
|
|
|
79
136
|
## The AI Written-Plan handoff
|
|
80
137
|
|
|
@@ -91,10 +148,13 @@ Dispatch stores the generated handoff in the ticket's AI Written-Plan field. It
|
|
|
91
148
|
- unresolved blockers
|
|
92
149
|
- scope boundaries
|
|
93
150
|
- autonomous policy
|
|
151
|
+
- declared verification commands and environment-variance checklist
|
|
94
152
|
- completion protocol
|
|
95
153
|
|
|
96
154
|
The short prompt passed to `hermes chat -q` is intentionally small. The ticket is the source of truth; the CLI argument is only a bootstrap pointer.
|
|
97
155
|
|
|
156
|
+
Board journal entries are framed as project constraints and lessons, not persona or roleplay instructions. Keep durable board entries focused on mechanisms, architectural/product boundaries, workflow invariants, public-product implications, and reusable pitfalls; use ticket fields/comments for run-specific chronology.
|
|
157
|
+
|
|
98
158
|
## Preserved worktrees
|
|
99
159
|
|
|
100
160
|
Use `--worktree` when the agent will edit code. Dispatch creates a normal git worktree under `.worktrees/` by default and gives the agent that directory as its working directory.
|
package/docs/SS-Orbit-Dark.png
CHANGED
|
File without changes
|
package/docs/SS-Orbit-Light.png
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/package.json
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/public/favicon-32x32.png
CHANGED
|
File without changes
|
package/public/index.html
CHANGED
|
@@ -15,9 +15,129 @@
|
|
|
15
15
|
sizes="180x180"
|
|
16
16
|
href="./apple-touch-icon.png"
|
|
17
17
|
/>
|
|
18
|
+
<!-- Apply the stored theme + motion preference before first paint, so
|
|
19
|
+
the app underneath the splash paints in the right theme (no flash)
|
|
20
|
+
and the splash respects an explicit reduce-motion choice. Mirrors
|
|
21
|
+
theme-preference.js (mab_theme) and motion-preference.js
|
|
22
|
+
(mab_reduce_motion → data-motion); main.js reconciles on load. -->
|
|
23
|
+
<script>
|
|
24
|
+
try {
|
|
25
|
+
var t = localStorage.getItem("mab_theme");
|
|
26
|
+
if (t === "light" || t === "dark")
|
|
27
|
+
document.documentElement.setAttribute("data-theme", t);
|
|
28
|
+
var rm = localStorage.getItem("mab_reduce_motion");
|
|
29
|
+
if (rm === "true")
|
|
30
|
+
document.documentElement.setAttribute("data-motion", "reduce");
|
|
31
|
+
else if (rm === "false")
|
|
32
|
+
document.documentElement.setAttribute("data-motion", "full");
|
|
33
|
+
} catch (e) {}
|
|
34
|
+
</script>
|
|
35
|
+
<link rel="preload" as="image" href="./orbits-logo.png" />
|
|
18
36
|
<link rel="stylesheet" href="/styles.css" />
|
|
37
|
+
<!-- Boot splash — the canonical ss-ui loading screen (see the package's
|
|
38
|
+
components/loader.css). Inline critical CSS so it paints before
|
|
39
|
+
/js/main.js loads. The logo grows in then breathes; no spinner.
|
|
40
|
+
Keyframes namespaced `ss-loader-*`. Under reduced motion the grow-in
|
|
41
|
+
is dropped and the dot grid stops; the gentle breathe stays. -->
|
|
42
|
+
<style>
|
|
43
|
+
.ss-loader {
|
|
44
|
+
position: fixed;
|
|
45
|
+
inset: 0;
|
|
46
|
+
z-index: 99999;
|
|
47
|
+
display: flex;
|
|
48
|
+
flex-direction: column;
|
|
49
|
+
align-items: center;
|
|
50
|
+
justify-content: center;
|
|
51
|
+
gap: 2rem;
|
|
52
|
+
overflow: hidden;
|
|
53
|
+
background: linear-gradient(
|
|
54
|
+
135deg,
|
|
55
|
+
#1a1a2e 0%,
|
|
56
|
+
#16213e 50%,
|
|
57
|
+
#0f3460 100%
|
|
58
|
+
);
|
|
59
|
+
transition: opacity 0.4s ease;
|
|
60
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI",
|
|
61
|
+
Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
62
|
+
}
|
|
63
|
+
.ss-loader::before {
|
|
64
|
+
content: "";
|
|
65
|
+
position: absolute;
|
|
66
|
+
width: 200%;
|
|
67
|
+
height: 200%;
|
|
68
|
+
background-image: radial-gradient(
|
|
69
|
+
circle,
|
|
70
|
+
rgba(168, 192, 255, 0.15) 1px,
|
|
71
|
+
transparent 1px
|
|
72
|
+
);
|
|
73
|
+
background-size: 50px 50px;
|
|
74
|
+
will-change: transform;
|
|
75
|
+
animation: ss-loader-drift 20s linear infinite;
|
|
76
|
+
}
|
|
77
|
+
.ss-loader.is-hiding {
|
|
78
|
+
opacity: 0;
|
|
79
|
+
pointer-events: none;
|
|
80
|
+
}
|
|
81
|
+
.ss-loader__logo {
|
|
82
|
+
width: 120px;
|
|
83
|
+
height: 120px;
|
|
84
|
+
object-fit: contain;
|
|
85
|
+
filter: drop-shadow(0 0 20px rgba(255, 255, 255, 0.3));
|
|
86
|
+
transform-origin: center;
|
|
87
|
+
will-change: transform;
|
|
88
|
+
animation:
|
|
89
|
+
ss-loader-grow 0.6s cubic-bezier(0.22, 1, 0.36, 1) both,
|
|
90
|
+
ss-loader-breathe 3s ease-in-out 0.6s infinite;
|
|
91
|
+
}
|
|
92
|
+
.ss-loader__label {
|
|
93
|
+
margin: 0;
|
|
94
|
+
color: #fff;
|
|
95
|
+
font-size: 1.25rem;
|
|
96
|
+
font-weight: 600;
|
|
97
|
+
letter-spacing: 0.5px;
|
|
98
|
+
text-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
|
|
99
|
+
}
|
|
100
|
+
@keyframes ss-loader-drift {
|
|
101
|
+
from { transform: translate(0, 0); }
|
|
102
|
+
to { transform: translate(-50px, -50px); }
|
|
103
|
+
}
|
|
104
|
+
@keyframes ss-loader-grow {
|
|
105
|
+
from { transform: scale(0); opacity: 0; }
|
|
106
|
+
to { transform: scale(1); opacity: 1; }
|
|
107
|
+
}
|
|
108
|
+
@keyframes ss-loader-breathe {
|
|
109
|
+
0%, 100% { transform: scale(1); }
|
|
110
|
+
50% { transform: scale(1.06); }
|
|
111
|
+
}
|
|
112
|
+
@media (prefers-reduced-motion: reduce) {
|
|
113
|
+
:root:not([data-motion="full"]) .ss-loader::before {
|
|
114
|
+
animation: none;
|
|
115
|
+
}
|
|
116
|
+
:root:not([data-motion="full"]) .ss-loader__logo {
|
|
117
|
+
animation: ss-loader-breathe 3s ease-in-out infinite;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
[data-motion="reduce"] .ss-loader::before {
|
|
121
|
+
animation: none;
|
|
122
|
+
}
|
|
123
|
+
[data-motion="reduce"] .ss-loader__logo {
|
|
124
|
+
animation: ss-loader-breathe 3s ease-in-out infinite;
|
|
125
|
+
}
|
|
126
|
+
</style>
|
|
19
127
|
</head>
|
|
20
128
|
<body>
|
|
129
|
+
<!-- Boot splash - shown immediately, removed once the app is ready. -->
|
|
130
|
+
<div id="ss-loader" class="ss-loader" role="status" aria-live="polite">
|
|
131
|
+
<img
|
|
132
|
+
class="ss-loader__logo"
|
|
133
|
+
src="./orbits-logo.png"
|
|
134
|
+
alt="Orbit"
|
|
135
|
+
width="120"
|
|
136
|
+
height="120"
|
|
137
|
+
/>
|
|
138
|
+
<p class="ss-loader__label">Loading Orbit…</p>
|
|
139
|
+
</div>
|
|
140
|
+
|
|
21
141
|
<div class="grain">
|
|
22
142
|
<div class="milky-way" aria-hidden="true"></div>
|
|
23
143
|
</div>
|
|
@@ -170,19 +290,10 @@
|
|
|
170
290
|
></div>
|
|
171
291
|
<aside id="drawer" class="drawer" hidden aria-label="Panel">
|
|
172
292
|
<header class="drawer-header">
|
|
173
|
-
<div
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
hidden
|
|
178
|
-
></span>
|
|
179
|
-
<h2 id="drawerTitle" class="drawer-title-text"></h2>
|
|
180
|
-
<div
|
|
181
|
-
id="drawerSubtitle"
|
|
182
|
-
class="drawer-subtitle"
|
|
183
|
-
hidden
|
|
184
|
-
></div>
|
|
185
|
-
</div>
|
|
293
|
+
<div
|
|
294
|
+
id="drawerTitleBlock"
|
|
295
|
+
class="drawer-title-block"
|
|
296
|
+
></div>
|
|
186
297
|
<nav
|
|
187
298
|
id="drawerTabs"
|
|
188
299
|
class="drawer-tabs"
|
|
@@ -310,5 +421,39 @@
|
|
|
310
421
|
</dialog>
|
|
311
422
|
|
|
312
423
|
<script src="/js/main.js" type="module"></script>
|
|
424
|
+
<!-- Fade out the boot splash once the DOM is ready. The /js/main.js
|
|
425
|
+
module runs before DOMContentLoaded, so theme/motion + wiring are
|
|
426
|
+
already applied by the time this fires. -->
|
|
427
|
+
<script>
|
|
428
|
+
(function () {
|
|
429
|
+
function hideSplash() {
|
|
430
|
+
var splash = document.getElementById("ss-loader");
|
|
431
|
+
if (!splash) return;
|
|
432
|
+
// Keep the splash up for a minimum of 786ms (measured from
|
|
433
|
+
// navigation start) so a fast load doesn't flash it in and out.
|
|
434
|
+
var wait = Math.max(0, 786 - performance.now());
|
|
435
|
+
setTimeout(function () {
|
|
436
|
+
splash.classList.add("is-hiding");
|
|
437
|
+
splash.addEventListener(
|
|
438
|
+
"transitionend",
|
|
439
|
+
function () {
|
|
440
|
+
splash.remove();
|
|
441
|
+
},
|
|
442
|
+
{ once: true }
|
|
443
|
+
);
|
|
444
|
+
setTimeout(function () {
|
|
445
|
+
splash.remove();
|
|
446
|
+
}, 600);
|
|
447
|
+
}, wait);
|
|
448
|
+
}
|
|
449
|
+
if (document.readyState === "loading") {
|
|
450
|
+
document.addEventListener("DOMContentLoaded", hideSplash, {
|
|
451
|
+
once: true
|
|
452
|
+
});
|
|
453
|
+
} else {
|
|
454
|
+
hideSplash();
|
|
455
|
+
}
|
|
456
|
+
})();
|
|
457
|
+
</script>
|
|
313
458
|
</body>
|
|
314
459
|
</html>
|
|
File without changes
|