@fapost/jig-ui 0.3.1-next.50 → 0.3.1-next.52
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/dist/http/app.js +31 -2
- package/dist/jig/client.js +22 -16
- package/dist/source/local.js +28 -7
- package/dist/web/assets/CanvasView-3MVSDFWS.js +1 -0
- package/dist/web/assets/{index-VC1NDKQv.js → index-CWaA0MWQ.js} +1 -1
- package/dist/web/index.html +1 -1
- package/package.json +1 -1
- package/dist/web/assets/CanvasView-CdYcFgSo.js +0 -1
package/dist/http/app.js
CHANGED
|
@@ -39,8 +39,8 @@ const field = (body, key) => typeof body === 'object' && body !== null ? body[ke
|
|
|
39
39
|
function place(v) {
|
|
40
40
|
if (v === 'top' || v === 'bottom')
|
|
41
41
|
return v;
|
|
42
|
-
const after = field(v, 'after');
|
|
43
|
-
return isId(after) ? { after } : undefined;
|
|
42
|
+
const [after, before] = [field(v, 'after'), field(v, 'before')];
|
|
43
|
+
return isId(after) ? { after } : isId(before) ? { before } : undefined;
|
|
44
44
|
}
|
|
45
45
|
/** A priority as the page sends it: 0 to 5, or `null` for none. */
|
|
46
46
|
const isPriority = (v) => v === null || (Number.isInteger(v) && v >= 0 && v <= 5);
|
|
@@ -138,6 +138,35 @@ function apiRoutes(source, version) {
|
|
|
138
138
|
return refuse(c, 422, 'usage', 'Give a task, a priority from 0 to 5 or null, and the revision it was read at.');
|
|
139
139
|
}
|
|
140
140
|
return written(c, await source.prioritise(c.req.param('id'), task, priority, revision));
|
|
141
|
+
})
|
|
142
|
+
// An epic is named by its spec and ordered among the top level of the queue, as a task is in its own level.
|
|
143
|
+
.post('/api/projects/:id/queue/epic/move', validator('json', (body) => {
|
|
144
|
+
const [epic, revision] = [field(body, 'epic'), field(body, 'revision')];
|
|
145
|
+
return {
|
|
146
|
+
epic: isId(epic) ? epic : undefined,
|
|
147
|
+
place: place(field(body, 'place')),
|
|
148
|
+
revision: isRevision(revision) ? revision : undefined,
|
|
149
|
+
};
|
|
150
|
+
}), async (c) => {
|
|
151
|
+
const { epic, place, revision } = c.req.valid('json');
|
|
152
|
+
if (epic === undefined || place === undefined || revision === undefined) {
|
|
153
|
+
return refuse(c, 422, 'usage', 'Give an epic, where it goes and the revision it was read at.');
|
|
154
|
+
}
|
|
155
|
+
return written(c, await source.moveEpic(c.req.param('id'), epic, place, revision));
|
|
156
|
+
})
|
|
157
|
+
.post('/api/projects/:id/queue/epic/priority', validator('json', (body) => {
|
|
158
|
+
const [epic, priority, revision] = [field(body, 'epic'), field(body, 'priority'), field(body, 'revision')];
|
|
159
|
+
return {
|
|
160
|
+
epic: isId(epic) ? epic : undefined,
|
|
161
|
+
priority: isPriority(priority) ? priority : undefined,
|
|
162
|
+
revision: isRevision(revision) ? revision : undefined,
|
|
163
|
+
};
|
|
164
|
+
}), async (c) => {
|
|
165
|
+
const { epic, priority, revision } = c.req.valid('json');
|
|
166
|
+
if (epic === undefined || priority === undefined || revision === undefined) {
|
|
167
|
+
return refuse(c, 422, 'usage', 'Give an epic, a priority from 0 to 5 or null, and the revision it was read at.');
|
|
168
|
+
}
|
|
169
|
+
return written(c, await source.prioritiseEpic(c.req.param('id'), epic, priority, revision));
|
|
141
170
|
})
|
|
142
171
|
// A pause is asked of the task, not made: Jig honours it at the task's next stage boundary.
|
|
143
172
|
.post('/api/projects/:id/queue/pause', validator('json', taskAt), async (c) => {
|
package/dist/jig/client.js
CHANGED
|
@@ -310,10 +310,10 @@ const SpecRow = z
|
|
|
310
310
|
const SpecList = z.object({ specs: z.array(SpecRow) });
|
|
311
311
|
/** The project's specs (`jig spec list --json`), in Jig's order. */
|
|
312
312
|
export async function readSpecs(root, platform = process.platform) {
|
|
313
|
-
const { data } = await readJson(root, ['spec', 'list'], platform);
|
|
314
|
-
return parsed(SpecList, data).specs;
|
|
313
|
+
const { revision, data } = await readJson(root, ['spec', 'list'], platform);
|
|
314
|
+
return { revision, specs: parsed(SpecList, data).specs };
|
|
315
315
|
}
|
|
316
|
-
/** A task in Jig's queue: its level (`null` the top, `epic:<spec>` an open epic's), its place there, its priority. */
|
|
316
|
+
/** A task or an epic in Jig's queue: its level (`null` the top, `epic:<spec>` an open epic's), its place there, its priority. */
|
|
317
317
|
const QueueItem = z.object({
|
|
318
318
|
kind: text,
|
|
319
319
|
id: text,
|
|
@@ -324,26 +324,32 @@ const QueueItem = z.object({
|
|
|
324
324
|
priority: z.int().min(0).max(5).nullable(),
|
|
325
325
|
});
|
|
326
326
|
const Queue = z.object({ items: z.array(QueueItem) });
|
|
327
|
-
/** The tasks in the project's queue (`jig queue list --json`), in Jig's order;
|
|
327
|
+
/** The tasks and the epics in the project's queue (`jig queue list --json`), in Jig's order; one not queued is not there. */
|
|
328
328
|
export async function readQueue(root, platform = process.platform) {
|
|
329
329
|
const { revision, data } = await readJson(root, ['queue', 'list'], platform);
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
return { revision, items };
|
|
330
|
+
const all = parsed(Queue, data).items;
|
|
331
|
+
const of = (kind) => all.filter((i) => i.kind === kind).map(({ id, level, position, priority }) => ({ id, level, position, priority }));
|
|
332
|
+
return { revision, items: of('task'), epics: of('epic') };
|
|
334
333
|
}
|
|
335
334
|
/**
|
|
336
|
-
* Moves a task in the queue (`jig queue move`), adding it when it is not there; refused as
|
|
337
|
-
* when anything was written in the clone since `revision`.
|
|
335
|
+
* Moves a task or an epic in the queue (`jig queue move`), adding it when it is not there; refused as
|
|
336
|
+
* `stale-revision` when anything was written in the clone since `revision`.
|
|
338
337
|
*/
|
|
339
|
-
export async function moveInQueue(root,
|
|
340
|
-
const
|
|
341
|
-
|
|
338
|
+
export async function moveInQueue(root, item, place, revision, platform = process.platform) {
|
|
339
|
+
const kind = item.slice(0, item.indexOf(':') + 1);
|
|
340
|
+
const where = place === 'top'
|
|
341
|
+
? ['--top']
|
|
342
|
+
: place === 'bottom'
|
|
343
|
+
? ['--bottom']
|
|
344
|
+
: 'after' in place
|
|
345
|
+
? ['--after', kind + place.after]
|
|
346
|
+
: ['--before', kind + place.before];
|
|
347
|
+
await readJson(root, ['queue', 'move', item, ...where, '--revision', String(revision)], platform);
|
|
342
348
|
}
|
|
343
|
-
/** Sets a task's priority in the queue (`jig queue set`), `null` for none; refused as `moveInQueue` is. */
|
|
344
|
-
export async function setPriority(root,
|
|
349
|
+
/** Sets a task's or an epic's priority in the queue (`jig queue set`), `null` for none; refused as `moveInQueue` is. */
|
|
350
|
+
export async function setPriority(root, item, priority, revision, platform = process.platform) {
|
|
345
351
|
const value = priority === null ? 'none' : String(priority);
|
|
346
|
-
await readJson(root, ['queue', 'set',
|
|
352
|
+
await readJson(root, ['queue', 'set', item, '--priority', value, '--revision', String(revision)], platform);
|
|
347
353
|
}
|
|
348
354
|
/** True when `version` is at least the minimum Jig UI reads. */
|
|
349
355
|
export function supports(version, minimum = MIN_JIG_VERSION) {
|
package/dist/source/local.js
CHANGED
|
@@ -132,10 +132,21 @@ async function readProject(project) {
|
|
|
132
132
|
},
|
|
133
133
|
tasks: { state: 'ready', tasks: live.map((t) => card(t, queued.get(t.id), resumes)), finished: finished.map(gone), revision },
|
|
134
134
|
details: live.map((t) => details(t, queued.get(t.id), status.attention, resumes)),
|
|
135
|
-
specs
|
|
135
|
+
// The specs are read beside the queue: a write of an epic carries the older of the two reads, or of the board's.
|
|
136
|
+
specs: { state: 'ready', specs: ordered(specs.specs, queue.epics), revision: Math.min(revision, specs.revision) },
|
|
136
137
|
revision,
|
|
137
138
|
};
|
|
138
139
|
}
|
|
140
|
+
/** The specs as the page shows them (`ProjectSpecs`): the queued epics by position, then the other open epics, then the rest. */
|
|
141
|
+
function ordered(specs, epics) {
|
|
142
|
+
const queued = new Map(epics.map((e) => [e.id, e]));
|
|
143
|
+
const shown = specs.map((s) => {
|
|
144
|
+
const q = s.epic?.state === 'open' ? queued.get(s.id) : undefined;
|
|
145
|
+
return { ...s, queue: q ? { position: q.position, priority: q.priority } : null };
|
|
146
|
+
});
|
|
147
|
+
const rank = (s) => (s.queue ? 0 : s.epic?.state === 'open' ? 1 : 2);
|
|
148
|
+
return shown.sort((a, b) => rank(a) - rank(b) || (a.queue && b.queue ? a.queue.position - b.queue.position : 0));
|
|
149
|
+
}
|
|
139
150
|
/** The version Jig's `upgrade-available` item in a read names for this machine; none without the item. */
|
|
140
151
|
const upgradeTo = (read) => read.view.state === 'ready' ? (read.view.attention.find((a) => a.kind === 'upgrade-available')?.versions?.to ?? undefined) : undefined;
|
|
141
152
|
/** A read that may have caught Jig mid-write: worth one more try before it is believed. */
|
|
@@ -318,15 +329,18 @@ export function localSource(configDir, { rescanMs = 60_000, quietMs, maxWaitMs }
|
|
|
318
329
|
* Jig itself listed reaches Jig's arguments; a new task's id names none, and the HTTP boundary checks it against
|
|
319
330
|
* Jig's grammar instead — then reads the project again, refused or not: the page reads next.
|
|
320
331
|
*/
|
|
321
|
-
|
|
332
|
+
/** A write naming `taskIds` among the live tasks of the last read, and `specIds` among its specs with an open epic. */
|
|
333
|
+
async function writing(id, taskIds, write, specIds = []) {
|
|
322
334
|
const project = (await readProjects(configDir)).find((p) => p.id === id);
|
|
323
335
|
if (!project)
|
|
324
336
|
return undefined;
|
|
325
|
-
const { tasks } = await shown(project);
|
|
337
|
+
const { tasks, specs } = await shown(project);
|
|
326
338
|
if (tasks.state !== 'ready')
|
|
327
339
|
return tasks;
|
|
328
|
-
|
|
340
|
+
const open = specs.state === 'ready' ? specs.specs.filter((s) => s.epic?.state === 'open').map((s) => s.id) : [];
|
|
341
|
+
if (!taskIds.every((t) => tasks.tasks.some((live) => live.id === t)) || !specIds.every((s) => open.includes(s))) {
|
|
329
342
|
return { state: 'refused', code: 'not-found' };
|
|
343
|
+
}
|
|
330
344
|
const entry = entryOf(project);
|
|
331
345
|
// Jig replaces its own scripts while it upgrades: the write waits for the person to try again.
|
|
332
346
|
if (entry.upgrade?.state === 'running')
|
|
@@ -383,11 +397,18 @@ export function localSource(configDir, { rescanMs = 60_000, quietMs, maxWaitMs }
|
|
|
383
397
|
return project && (await shown(project)).specs;
|
|
384
398
|
},
|
|
385
399
|
move(id, taskId, place, revision) {
|
|
386
|
-
const named = typeof place === 'object' ? [taskId, place.after] : [taskId];
|
|
387
|
-
return writing(id, named, (root) => moveInQueue(root, taskId
|
|
400
|
+
const named = typeof place === 'object' ? [taskId, 'after' in place ? place.after : place.before] : [taskId];
|
|
401
|
+
return writing(id, named, (root) => moveInQueue(root, `task:${taskId}`, place, revision));
|
|
402
|
+
},
|
|
403
|
+
moveEpic(id, specId, place, revision) {
|
|
404
|
+
const named = typeof place === 'object' ? [specId, 'after' in place ? place.after : place.before] : [specId];
|
|
405
|
+
return writing(id, [], (root) => moveInQueue(root, `epic:${specId}`, place, revision), named);
|
|
406
|
+
},
|
|
407
|
+
prioritiseEpic(id, specId, priority, revision) {
|
|
408
|
+
return writing(id, [], (root) => setPriority(root, `epic:${specId}`, priority, revision), [specId]);
|
|
388
409
|
},
|
|
389
410
|
prioritise(id, taskId, priority, revision) {
|
|
390
|
-
return writing(id, [taskId], (root) => setPriority(root, taskId
|
|
411
|
+
return writing(id, [taskId], (root) => setPriority(root, `task:${taskId}`, priority, revision));
|
|
391
412
|
},
|
|
392
413
|
requestPause(id, taskId, revision) {
|
|
393
414
|
return writing(id, [taskId], (root) => requestPause(root, taskId, revision));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{$ as e,A as t,B as n,C as r,D as i,E as a,F as o,G as s,H as c,I as l,J as u,K as ee,L as d,M as f,N as p,O as te,P as m,Q as h,R as ne,S as g,T as _,U as v,V as y,W as b,X as x,Y as S,Z as C,_ as w,a as T,at as E,b as re,c as ie,d as D,et as O,f as ae,g as k,h as oe,i as se,it as ce,j as le,k as ue,l as de,m as fe,n as pe,nt as A,o as me,p as j,q as M,r as N,rt as P,s as F,t as he,tt as I,u as ge,v as _e,w as ve,x as L,y as ye,z as be}from"./index-CWaA0MWQ.js";var xe=S({__name:`BaseSeparator`,props:{orientation:{type:String,required:!1,default:`horizontal`},decorative:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},setup(e){let t=e,n=[`horizontal`,`vertical`];function r(e){return n.includes(e)}let i=y(()=>r(t.orientation)?t.orientation:`horizontal`),a=y(()=>i.value===`vertical`?t.orientation:void 0),o=y(()=>t.decorative?{role:`none`}:{"aria-orientation":a.value,role:`separator`});return(t,n)=>(h(),v(A(m),C({as:e.as,"as-child":e.asChild,"data-orientation":i.value},o.value),{default:I(()=>[O(t.$slots,`default`)]),_:3},16,[`as`,`as-child`,`data-orientation`]))}}),Se=S({__name:`Separator`,props:{orientation:{type:String,required:!1,default:`horizontal`},decorative:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},setup(e){let t=e;return(e,n)=>(h(),v(xe,ce(x(t)),{default:I(()=>[O(e.$slots,`default`)]),_:3},16))}}),Ce=S({__name:`CardContent`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(e){let t=e;return(e,n)=>(h(),s(`div`,{"data-slot":`card-content`,class:P(A(o)(`px-4 group-data-[size=sm]/card:px-3`,t.class))},[O(e.$slots,`default`)],2))}}),we=S({__name:`CardDescription`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(e){let t=e;return(e,n)=>(h(),s(`div`,{"data-slot":`card-description`,class:P(A(o)(`text-xs/relaxed text-muted-foreground`,t.class))},[O(e.$slots,`default`)],2))}}),Te=S({__name:`CardHeader`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(e){let t=e;return(e,n)=>(h(),s(`div`,{"data-slot":`card-header`,class:P(A(o)(`group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-none px-4 group-data-[size=sm]/card:px-3 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3`,t.class))},[O(e.$slots,`default`)],2))}}),Ee=S({__name:`CardTitle`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(e){let t=e;return(e,n)=>(h(),s(`div`,{"data-slot":`card-title`,class:P(A(o)(`cn-font-heading text-sm font-medium group-data-[size=sm]/card:text-sm`,t.class))},[O(e.$slots,`default`)],2))}}),R=S({__name:`Separator`,props:{orientation:{default:`horizontal`},decorative:{type:Boolean,default:!0},asChild:{type:Boolean},as:{},class:{type:[Boolean,null,String,Object,Array]}},setup(e){let n=e,r=t(n,`class`);return(e,t)=>(h(),v(A(Se),C({"data-slot":`separator`},A(r),{class:A(o)(`shrink-0 bg-border data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px data-[orientation=vertical]:self-stretch`,n.class)}),null,16,[`class`]))}}),De=[`aria-label`],Oe={class:`flex items-baseline gap-3 border-b bg-muted/50 px-4 py-2`},ke={class:`font-semibold tracking-wider uppercase`},Ae={key:0,class:`text-muted-foreground`},je={class:`grid grid-cols-1 divide-y lg:grid-cols-2 lg:divide-x lg:divide-y-0`},z=S({__name:`CanvasSection`,props:{title:{},note:{}},setup(t){return(r,i)=>(h(),s(`section`,{"aria-label":t.title,class:`border-b`},[c(`h2`,Oe,[c(`span`,ke,E(t.title),1),t.note?(h(),s(`span`,Ae,E(t.note),1)):b(``,!0)]),c(`div`,je,[(h(),s(n,null,e([`light`,`dark`],e=>c(`div`,{key:e,class:P([e,`flex flex-col gap-4 bg-background p-4 text-foreground`])},[O(r.$slots,`default`)],2)),64))])],8,De))}}),B=(e,t)=>({id:e,class:`T2`,status:`active`,goal:null,paused:!1,pauseRequest:null,pauseRequestable:!0,resumable:!1,resumesTo:null,started:!0,gate:null,autopilot:null,pullRequest:null,priority:null,queue:null,...t}),V=(e,t)=>({url:`https://github.com/fapost-lab/jig-ui/pull/18`,state:e,ci:t,fetchedAt:`2026-10-18T09:40:00Z`}),H=[B(`design-system`,{class:`T3`,gate:`waiting`,priority:0,queue:{level:null,position:100},goal:`shadcn-vue on Tailwind v4 with light and dark themes; #/canvas with every component in every variant; the three screens rebuilt on it.`}),B(`registry-schema`,{gate:`changed`,priority:3,queue:{level:null,position:200},goal:`Version the registry file so a newer Jig UI can read an older one.`}),B(`pause-request`,{class:`T3`,autopilot:`stopped`,goal:`A drop on the paused column writes a sticky request through Jig; the card shows it with its age and a cancel.`}),B(`specs-and-epics`,{autopilot:`on`,queue:{level:null,position:300},goal:`Show each spec with its phases, progress and epic branch beside the board, from Jig's spec list.`}),B(`task-details`,{status:`ready`,pullRequest:V(`open`,`green`),goal:`Open a task's details from its card.`}),B(`refusal-fixture`,{class:`T0`,status:`ready`,pullRequest:V(`open`,`red`),goal:`Replace the refusal text in task-list-states.json with one Jig prints.`}),B(`docs-board`,{class:`T1`,status:`ready`,pullRequest:V(`open`,`pending`),goal:`Describe the five columns on the projects page of the docs.`}),B(`live-updates`,{status:`ready`,pullRequest:V(`merged`,`none`),goal:`Follow connected projects without a reload.`}),B(`no-pr-yet`,{class:`T1`,status:`ready`,goal:`Ready, nothing pushed.`}),B(`jig-init-hook`,{class:`T3`,paused:!0,pauseRequestable:!1,goal:`Register a project in an installed Jig UI from jig init.`}),B(`file-backlog-task`,{class:null,started:!1,goal:`File a minimal backlog task from the page through jig task new.`}),B(`a-task-with-a-rather-long-identifier-that-wraps`,{goal:null}),B(`conflict-display`,{pauseRequest:{requestedAt:`2026-10-22T09:00:00Z`},pauseRequestable:!1,goal:`Show what changed when a write was based on a stale read.`}),B(`resume-from-page`,{class:`T3`,paused:!0,pauseRequestable:!1,resumable:!0,resumesTo:`in-progress`,goal:`A drop out of Paused, or the card menu, resumes the task through jig task resume.`})],U=[{id:`needs-you`,title:`Needs you`,cards:H.slice(0,3)},{id:`in-progress`,title:`In progress`,cards:[H[3],H[12],H[11]]},{id:`ready`,title:`Ready`,cards:H.slice(4,9)},{id:`backlog`,title:`Backlog`,cards:[H[10]]},{id:`paused`,title:`Paused`,cards:[H[9],H[13]]}],W=U.map(e=>({...e,cards:[]})),Me=[{id:`file-backlog-task`,status:`consolidated`,goal:`File a minimal backlog task from the page.`,updatedAt:`2026-10-25`,pullRequest:{url:`https://github.com/fapost-lab/jig-ui/pull/40`,state:`merged`}},{id:`pr-template`,status:`abandoned`,goal:`A pull request template.`,updatedAt:`2026-10-17`,pullRequest:null},{id:`old-spike`,status:`abandoned`,goal:null,updatedAt:`2026-10-12`,pullRequest:null}],Ne=[{id:`needs-you`,title:`Needs you`,count:3},{id:`in-progress`,title:`In progress`,count:1},{id:`ready`,title:`Ready`,count:5},{id:`backlog`,title:`Backlog`,count:1},{id:`paused`,title:`Paused`,count:1},{id:`unknown`,title:`A column this page does not know`,count:0}],G=[{kind:`gate`,subject:{type:`task`,id:`design-system`},tasks:[`design-system`],title:`Design waits at its gate`,detail:null,todo:`Review the design and approve it: jig task gate design-system approved`,url:null,versions:null},{kind:`pull-request-ci-failed`,subject:{type:`task`,id:`refusal-fixture`},tasks:[`refusal-fixture`],title:`CI failed`,detail:`pull request #19`,todo:`Look at the failing check.`,url:`https://github.com/fapost-lab/jig-ui/pull/19`,versions:null},{kind:`housekeeping`,subject:{type:`project`,id:null},tasks:[],title:`Housekeeping never ran`,detail:null,todo:`Run jig housekeeping.`,url:`https://example.com/docs`,versions:null}],K=[{id:`approve-gate`,command:`jig task gate design-system approved`},{id:`answer-stop`,command:`jig task autopilot pause-request resume --answer <text>`},{id:`pause`,command:`jig task pause design-system`},{id:`request-pause`,command:`jig queue request task:design-system pause`},{id:`something-new`,command:`jig task something-new design-system`}],Pe={state:`ready`,issue:null,baseBranch:`main`,createdAt:`2026-10-17`,updatedAt:`2026-10-18`,knowledgeConsolidated:!1,worktree:null,gateBy:null,run:null,housekeepingFlags:[],attention:[]},q=[{...Pe,...H[2],gate:`approved`,gateBy:`human`,branch:`task/pause-request`,worktree:{uncommitted:4},issue:`#42`,pullRequest:V(`open`,`red`),run:{mode:`attended`,stage:`implement`,stageAt:`2026-10-18T09:00:00Z`,stopReason:`Which column takes a paused task that already has an open pull request?`,stopAt:`2026-10-18T09:12:00Z`,phase:null},housekeepingFlags:[`needs-consolidation`],attention:[G[0]],actions:K,column:{id:`needs-you`,title:`Needs you`}},{...Pe,...H[10],branch:null,actions:[{id:`start`,command:`jig task start file-backlog-task`}],column:{id:`backlog`,title:`Backlog`}}],J=(e,t={})=>({id:e,state:`ready`,jigVersion:`0.29.0`,counts:{active:11,paused:1,ready:3},attention:[],housekeepingStale:!1,upgrade:null,...t}),Y=[J(`jig-ui`,{attention:G,housekeepingStale:!0}),J(`nextjs-store`,{counts:{active:0,paused:0,ready:0}}),J(`legacy-shop`,{jigVersion:`0.34.0`,counts:{active:2,paused:0,ready:0},attention:[{kind:`upgrade-available`,subject:{type:`project`,id:null},tasks:[],title:`Jig in this project is older than on this machine`,detail:`this project runs 0.34.0; this machine has 0.35.0`,todo:`jig upgrade`,url:null,versions:{from:`0.34.0`,to:`0.35.0`}}]}),{id:`old-jig`,state:`unsupported`,jigVersion:`0.26.0`,minimum:`0.29.0`,upgrade:null},{id:`new-jig`,state:`incompatible`,jigVersion:`1.0.0`,upgrade:null},{id:`busy`,state:`unreadable`,code:`locked`,upgrade:null},{id:`moved`,state:`unavailable`,reason:`missing`,upgrade:null}],X={mode:`copy`,from:`0.34.0`,to:`0.35.0`,outcome:`planned`,git:null,manualSteps:[],wouldStop:[]},Fe=[{state:`reading`},{state:`planned`,plan:X},{state:`planned`,plan:{...X,manualSteps:[`Restart your agent sessions: the skills changed.`]}},{state:`planned`,plan:{...X,wouldStop:["the working tree has uncommitted changes; commit them, stash them (`git stash`), or finish the task they belong to, then run `jig upgrade` again"]}},{state:`refused`,message:`Jig refused the upgrade.`}],Z={level:`pr`,branch:`jig/upgrade-0.35.0`,commit:`279390b`,pushed:!0,pullRequest:`https://github.com/fapost-lab/jig-ui/pull/49`,merged:!1},Q=e=>({state:`done`,at:`2026-10-27T08:00:00Z`,upgrade:{...X,outcome:`upgraded`,git:Z,...e}}),Ie=[{state:`running`,since:new Date(Date.now()-12e4).toISOString(),to:`0.35.0`},Q({git:{...Z,merged:!0}}),Q({manualSteps:[`Restart your agent sessions: the skills changed.`]}),Q({outcome:`staged`,git:{...Z,level:`none`,commit:null,pushed:!1,pullRequest:null}}),Q({outcome:`nothing-to-do`,git:null}),{state:`refused`,at:`2026-10-27T08:00:00Z`,code:`upgrade-blocked`,reasons:[`task up-x is started and its branch task/up-x is checked out here (record .ai/runtime/working/up-x); the upgrade would take this checkout off it`]},{state:`refused`,at:`2026-10-27T08:00:00Z`,code:`failed`,reasons:[]}],$=[{text:"`design-system` — design system and canvas",checked:!0,task:`design-system`,fog:!1},{text:"`specs-and-epics` — specs and epics (after: project board — `jig spec list`)",checked:!1,task:`specs-and-epics`,fog:!1},{text:"`old-task` — a task no longer live",checked:!1,task:`old-task`,fog:!1},{text:`invoices from orders, no task filed yet`,checked:!1,task:null,fog:!1},{text:"fog: registration by `jig init`",checked:!1,task:null,fog:!0}],Le=[{id:`jig-ui`,title:`Jig UI — a local control center for Jig projects`,missingFiles:[],release:null,epic:null,progress:{done:2,total:6,filed:2,fog:1},phases:[{phase:0,title:`Package and release`,done:1,total:1,filed:0,fog:0,items:[{...$[0],text:`package and release`,task:null}]},{phase:1,title:`Read-only UI`,done:1,total:5,filed:2,fog:1,items:$}],queue:null},{id:`billing`,title:`Billing in one place`,missingFiles:[],release:`minor`,epic:{branch:`epic/billing`,state:`open`,checkedOut:!1,missing:!1,fetched:!0},progress:{done:0,total:1,filed:0,fog:0},phases:[{phase:null,title:null,done:0,total:1,filed:0,fog:0,items:[$[3]]}],queue:{position:100,priority:1}},{id:`lost-epic`,title:`An epic whose branch is gone`,missingFiles:[],release:`major`,epic:{branch:`epic/lost`,state:`open`,checkedOut:!0,missing:!0,fetched:!1},progress:null,phases:[],queue:null},{id:`half-written`,title:null,missingFiles:[`spec.md`,`roadmap.md`],release:null,epic:null,progress:null,phases:[],queue:null}],Re={class:`flex gap-4`},ze={class:`w-24 text-muted-foreground`},Be={class:`flex items-center gap-2`},Ve={class:`flex flex-wrap gap-2`},He={class:`flex max-w-sm flex-col gap-2`},Ue={class:`flex h-5 items-center gap-2`},We={class:`flex gap-2`},Ge={class:`flex flex-wrap items-center gap-6`},Ke={class:`flex items-center gap-1`},qe={class:`grid grid-cols-2 gap-2 xl:grid-cols-3`},Je={class:`flex h-[28rem] flex-col`},Ye={class:`flex h-40 flex-col`},Xe={class:`flex h-[28rem] flex-col`},Ze={class:`flex h-64 flex-col`},Qe={class:`flex h-64 flex-col`},$e=S({__name:`CanvasView`,setup(t){let o=[`default`,`secondary`,`outline`,`ghost`,`destructive`,`link`],m=[`xs`,`sm`,`default`,`lg`],y=[`icon-xs`,`icon-sm`,`icon`,`icon-lg`],b=[`default`,`secondary`,`outline`,`ghost`,`destructive`,`link`],x=[`attention`,`good`,`bad`,`quiet`];return(t,S)=>(h(),s(`div`,null,[S[14]||=c(`div`,{class:`border-b px-4 py-3`},[c(`h1`,{class:`font-semibold tracking-wider uppercase`},`Canvas`),c(`p`,{class:`text-muted-foreground`},`Every component of the page in every variant and state; the left panel light, the right dark.`)],-1),u(z,{title:`Tones`,note:`lib/tones.ts — the only colours with a meaning`},{default:I(()=>[(h(),s(n,null,e(x,e=>c(`p`,{key:e,class:P(A(ne)[e])},E(e)+` as a rule`,3)),64)),c(`p`,Re,[(h(),s(n,null,e(x,e=>c(`span`,{key:e,class:P(A(be)[e])},E(e),3)),64))])]),_:1}),S[15]||=c(`h2`,{class:`border-b px-4 py-2 font-bold tracking-widest uppercase`},`components/ui`,-1),u(z,{title:`Button`,note:`variant × size; icon sizes; disabled`},{default:I(()=>[(h(),s(n,null,e(o,t=>c(`div`,{key:t,class:`flex flex-wrap items-center gap-2`},[c(`span`,ze,E(t),1),(h(),s(n,null,e(m,e=>u(A(p),{key:e,variant:t,size:e},{default:I(()=>[M(E(e),1)]),_:2},1032,[`variant`,`size`])),64)),u(A(p),{variant:t,disabled:``},{default:I(()=>[...S[0]||=[M(`disabled`,-1)]]),_:1},8,[`variant`])])),64)),c(`div`,Be,[S[2]||=c(`span`,{class:`w-24 text-muted-foreground`},`icon`,-1),(h(),s(n,null,e(y,e=>u(A(p),{key:e,variant:`outline`,size:e,"aria-label":e},{default:I(()=>[u(A(l))]),_:1},8,[`size`,`aria-label`])),64)),u(A(p),{variant:`outline`,size:`sm`},{default:I(()=>[u(A(l),{"data-icon":`inline-start`}),S[1]||=M(`with icon`,-1)]),_:1})])]),_:1}),u(z,{title:`Badge`},{default:I(()=>[c(`div`,Ve,[(h(),s(n,null,e(b,e=>u(A(ue),{key:e,variant:e},{default:I(()=>[M(E(e),1)]),_:2},1032,[`variant`])),64))])]),_:1}),u(z,{title:`Card`},{default:I(()=>[u(A(te),{class:`max-w-sm`},{default:I(()=>[u(A(Te),null,{default:I(()=>[u(A(Ee),null,{default:I(()=>[...S[3]||=[M(`Card title`,-1)]]),_:1}),u(A(we),null,{default:I(()=>[...S[4]||=[M(`Card description, muted.`,-1)]]),_:1})]),_:1}),u(A(Ce),null,{default:I(()=>[...S[5]||=[M(`Card content.`,-1)]]),_:1})]),_:1})]),_:1}),u(z,{title:`Input and Label`,note:`empty, filled, invalid, disabled`},{default:I(()=>[c(`div`,He,[u(A(ae),null,{default:I(()=>[...S[6]||=[M(`Project path`,-1)]]),_:1}),u(A(j),{placeholder:`/path/to/project`}),u(A(j),{"model-value":`/Users/me/project`}),u(A(j),{"model-value":`/not/a/project`,"aria-invalid":`true`}),u(A(j),{"model-value":`disabled`,disabled:``})])]),_:1}),u(z,{title:`Separator`},{default:I(()=>[u(A(R)),c(`div`,Ue,[S[7]||=M(`left`,-1),u(A(R),{orientation:`vertical`}),S[8]||=M(`right`,-1)])]),_:1}),u(z,{title:`ToggleGroup`,note:`the Board / List switch`},{default:I(()=>[u(A(me),{type:`single`,variant:`outline`,size:`sm`,"model-value":`board`,"aria-label":`View`},{default:I(()=>[u(A(T),{value:`board`},{default:I(()=>[...S[9]||=[M(`Board`,-1)]]),_:1}),u(A(T),{value:`list`},{default:I(()=>[...S[10]||=[M(`List`,-1)]]),_:1})]),_:1})]),_:1}),u(z,{title:`Toggle`,note:`the board's finished tasks: off, on`},{default:I(()=>[c(`div`,We,[u(A(F),{variant:`outline`,size:`sm`,"model-value":!1},{default:I(()=>[...S[11]||=[M(`3 finished tasks`,-1)]]),_:1}),u(A(F),{variant:`outline`,size:`sm`,"model-value":!0},{default:I(()=>[...S[12]||=[M(`3 finished tasks`,-1)]]),_:1})])]),_:1}),u(z,{title:`Collapsible`,note:`open and folded`},{default:I(()=>[(h(),s(n,null,e([!0,!1],e=>u(A(re),{key:String(e),"default-open":e},{default:I(()=>[u(A(_e),{class:`w-full border-b bg-muted/50 px-3 py-1.5 text-left`},{default:I(()=>[M(`Trigger (`+E(e?`open`:`folded`)+`)`,1)]),_:2},1024),u(A(ye),{class:`px-3 py-2`},{default:I(()=>[...S[13]||=[M(`Content`,-1)]]),_:1})]),_:2},1032,[`default-open`])),64))]),_:1}),S[16]||=c(`h2`,{class:`border-b px-4 py-2 font-bold tracking-widest uppercase`},`components`,-1),u(z,{title:`ProjectTabs`,note:`on the workspace; on a project; empty`},{default:I(()=>[u(d,{projects:A(Y),version:`0.1.0`},{default:I(()=>[u(f)]),_:1},8,[`projects`]),u(d,{projects:A(Y),current:`jig-ui`,version:`0.1.0`},null,8,[`projects`]),u(d,{projects:[]})]),_:1}),u(z,{title:`ThemeToggle`,note:`switches the whole page; the icon is the theme it switches to`},{default:I(()=>[c(`div`,null,[u(f)])]),_:1}),u(z,{title:`ProjectCard`,note:`ready with attention and stale housekeeping; nothing needs you; its Jig older than the machine's, Upgrade… offered; each state it cannot be read in`},{default:I(()=>[(h(!0),s(n,null,e(A(Y),e=>(h(),v(he,{key:e.id,project:e},null,8,[`project`]))),128))]),_:1}),u(z,{title:`UpgradePanel`,note:`on a card: reading the dry run; the plan, with steps by hand; a stop; a refusal; under way; merged, with steps by hand, staged, nothing to do; not started; failed`},{default:I(()=>[(h(!0),s(n,null,e(A(Fe),(e,t)=>(h(),v(pe,{key:`plan-${t}`,project:`legacy-shop`,run:null,plan:e},null,8,[`plan`]))),128)),(h(!0),s(n,null,e(A(Ie),(e,t)=>(h(),v(pe,{key:`run-${t}`,project:`legacy-shop`,run:e,plan:void 0},null,8,[`run`]))),128))]),_:1}),u(z,{title:`NewTaskForm`,note:`empty, on its way, the id taken`},{default:I(()=>[u(D,{busy:!1}),u(D,{busy:!0,task:`fix-login`,goal:`Log in with the token after a restart.`}),u(D,{busy:!1,task:`queue-reorder`,goal:`Order the work.`,refusal:`The project has a task called queue-reorder already, maybe a finished one. Choose another id.`,taken:``})]),_:1}),u(z,{title:`ConnectForm`,note:`idle, busy, refused`},{default:I(()=>[u(N,{busy:!1}),u(N,{busy:!0,"model-value":`/Users/me/project`}),u(N,{busy:!1,"model-value":`/Users/me/project/.claude/worktrees/x`,refusal:`That is a worktree. Connect the main checkout instead.`})]),_:1}),u(z,{title:`AttentionItem`,note:`no link; a pull request; another link`},{default:I(()=>[(h(!0),s(n,null,e(A(G),(e,t)=>(h(),v(se,{key:t,item:e},null,8,[`item`]))),128))]),_:1}),u(z,{title:`ColumnHeader`,note:`each column, and one this page does not know`},{default:I(()=>[(h(!0),s(n,null,e(A(Ne),e=>(h(),v(le,{id:e.id,key:e.id,title:e.title,count:e.count},null,8,[`id`,`title`,`count`]))),128))]),_:1}),u(z,{title:`QueueMenu`,note:`press to open: To top, Up, Down, To bottom, Priority, the pause — first queued, in the middle, not queued, last, paused under a Jig that cannot resume it (no pause to ask, Resume off), paused and resumable, a pause asked, while its change is on its way`},{default:I(()=>[c(`div`,Ge,[(h(!0),s(n,null,e([A(H)[0],A(H)[1],A(H)[3],A(H)[11],A(H)[9],A(H)[13],A(H)[12]],e=>(h(),s(`span`,{key:e.id,class:`flex items-center gap-1`},[M(E(e.id),1),u(i,{task:e,cards:A(H)},null,8,[`task`,`cards`])]))),128)),c(`span`,Ke,[M(E(A(H)[1].id),1),u(i,{task:A(H)[1],cards:A(H),disabled:``},null,8,[`task`,`cards`])])])]),_:1}),u(z,{title:`TaskCard`,note:`every note a card carries, a priority among them; with its queue menu; while its change is on its way; changed since a refused change; open with details, while reading, unreadable`},{default:I(()=>[c(`div`,qe,[(h(!0),s(n,null,e(A(H),e=>(h(),v(g,{key:e.id,project:`jig-ui`,task:e,open:!1},null,8,[`task`]))),128)),u(g,{project:`jig-ui`,task:A(H)[1],open:!1,cards:A(H)},null,8,[`task`,`cards`]),u(g,{project:`jig-ui`,task:A(H)[0],open:!1,cards:A(H),busy:``},null,8,[`task`,`cards`]),u(g,{project:`jig-ui`,task:A(H)[3],open:!1,cards:A(H),changed:``},null,8,[`task`,`cards`]),u(g,{project:`jig-ui`,task:A(H)[2],open:!0,details:A(q)[0]},null,8,[`task`,`details`]),u(g,{project:`jig-ui`,task:A(H)[0],open:!0},null,8,[`task`]),u(g,{project:`jig-ui`,task:A(H)[1],open:!0,details:`unavailable`},null,8,[`task`])])]),_:1}),u(z,{title:`TaskRow`,note:`each note and priority; selected; with its queue menu; while its change is on its way; changed since a refused change`},{default:I(()=>[c(`div`,null,[(h(!0),s(n,null,e(A(H),(e,t)=>(h(),v(w,{key:e.id,task:e,selected:t===2},null,8,[`task`,`selected`]))),128)),u(w,{task:A(H)[1],selected:!1,cards:A(H)},null,8,[`task`,`cards`]),u(w,{task:A(H)[0],selected:!1,cards:A(H),busy:``},null,8,[`task`,`cards`]),u(w,{task:A(H)[3],selected:!1,cards:A(H),changed:``},null,8,[`task`,`cards`])])]),_:1}),u(z,{title:`BoardColumns`,note:`cards in every column, one open with its details, two changed since a refused change; no live task`},{default:I(()=>[c(`div`,Je,[u(L,{project:`jig-ui`,columns:A(U),selected:A(H)[2].id,details:A(q)[0],pending:A(H)[0].id,changed:[A(H)[1].id,A(H)[3].id]},null,8,[`columns`,`selected`,`details`,`pending`,`changed`])]),c(`div`,Ye,[u(L,{project:`jig-ui`,columns:A(W)},null,8,[`columns`])])]),_:1}),u(z,{title:`BoardList`,note:`a row picked with its details; nothing picked; no live task`},{default:I(()=>[c(`div`,Xe,[u(k,{project:`jig-ui`,columns:A(U),selected:A(H)[2].id,details:A(q)[0]},null,8,[`columns`,`selected`,`details`])]),c(`div`,Ze,[u(k,{project:`jig-ui`,columns:A(U)},null,8,[`columns`])]),c(`div`,Qe,[u(k,{project:`jig-ui`,columns:A(W)},null,8,[`columns`])])]),_:1}),u(z,{title:`FinishedList`,note:`closed with its pull request merged; abandoned; one without a goal`},{default:I(()=>[u(fe,{tasks:A(Me),class:`border`},null,8,[`tasks`])]),_:1}),u(z,{title:`TaskFacts`,note:`everything a task can carry; a task not started`},{default:I(()=>[(h(!0),s(n,null,e(A(q),e=>(h(),v(ve,{key:e.id,details:e,class:`border-b pb-3`},null,8,[`details`]))),128))]),_:1}),u(z,{title:`TaskBrief`,note:`facts, actions and the link to the full page`},{default:I(()=>[u(r,{project:`jig-ui`,task:A(q)[1].id,details:A(q)[1]},null,8,[`task`,`details`])]),_:1}),u(z,{title:`ActionList`,note:`Jig's offers, one unknown id; none`},{default:I(()=>[u(_,{actions:A(K)},null,8,[`actions`]),u(_,{actions:[]})]),_:1}),u(z,{title:`CopyCommand`,note:`short; long enough to be cut`},{default:I(()=>[u(a,{command:`jig task pause design-system`}),u(a,{command:`jig task autopilot a-task-with-a-rather-long-identifier-that-wraps resume --answer 'a long answer to the question'`,class:`max-w-xs`})]),_:1}),u(z,{title:`ProgressBar`,note:`none, part, all, an empty roadmap`},{default:I(()=>[(h(),s(n,null,e([[0,4],[3,9],[5,5],[0,0]],([e,t])=>u(ge,{key:`${e}/${t}`,done:e,total:t},null,8,[`done`,`total`])),64))]),_:1}),u(z,{title:`SpecItemRow`,note:`done with a live task; open with dependencies; a task no longer live; no task; fog`},{default:I(()=>[c(`ul`,null,[(h(!0),s(n,null,e(A($),(e,t)=>(h(),v(de,{key:t,item:e,project:`jig-ui`,live:t<2},null,8,[`item`,`live`]))),128))])]),_:1}),u(z,{title:`SpecCard`,note:`no epic, a finished phase folded; an open epic in the queue at P1, with its queue menu; a lost epic branch, not queued, with its change on its way; missing files`},{default:I(()=>[(h(!0),s(n,null,e(A(Le),e=>(h(),v(ie,{key:e.id,spec:e,project:`jig-ui`,live:[`design-system`,`specs-and-epics`],busy:e.id===`lost-epic`},ee({_:2},[e.epic?.state===`open`?{name:`menu`,fn:I(()=>[u(oe,{spec:e,specs:A(Le),disabled:e.id===`lost-epic`},null,8,[`spec`,`specs`,`disabled`])]),key:`0`}:void 0]),1032,[`spec`,`busy`]))),128))]),_:1})]))}});export{$e as default};
|