From 8aaca14e3ad847d029e7962aa9e38170f38cc5c1 Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 23 Feb 2026 16:44:17 -0600 Subject: [PATCH] updated comments Signed-off-by: Max --- scripts/gantt.sh | 2 +- src/app/api/tasks/route.ts | 4 +- src/app/page.tsx | 47 +- src/app/tasks/[taskId]/page.tsx | 72 +- src/stores/useTaskStore.ts | 81 +- supabase/tasks.json | 1177 ++++++++++++++++++++++++ supabase/update_task_comments_only.sql | 22 + 7 files changed, 1269 insertions(+), 136 deletions(-) create mode 100644 supabase/tasks.json create mode 100644 supabase/update_task_comments_only.sql diff --git a/scripts/gantt.sh b/scripts/gantt.sh index c28d962..64389b1 100755 --- a/scripts/gantt.sh +++ b/scripts/gantt.sh @@ -215,7 +215,7 @@ cmd_task_comment() { --arg id "$comment_id" \ --arg text "$text" \ --arg createdAt "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ - '{id: $id, text: $text, createdAt: $createdAt, author: "assistant"}') + '{id: $id, text: $text, createdAt: $createdAt, commentAuthorId: "assistant", replies: []}') local updated_task updated_task=$(echo "$task" | jq --argjson comment "$new_comment" '.comments += [$comment]') diff --git a/src/app/api/tasks/route.ts b/src/app/api/tasks/route.ts index 450563c..c1a6c05 100644 --- a/src/app/api/tasks/route.ts +++ b/src/app/api/tasks/route.ts @@ -231,7 +231,7 @@ function mapTaskRow(row: Record, usersById: Map, usersById: Map typeof tag === "string"), attachments: includeFullData ? (row.attachments as unknown[] | undefined) ?? [] : [], }; diff --git a/src/app/page.tsx b/src/app/page.tsx index dbf6933..e2538aa 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -35,7 +35,7 @@ import { markdownPreviewObjectUrl, textPreviewObjectUrl, } from "@/lib/attachments" -import { useTaskStore, Task, TaskType, TaskStatus, Priority, TaskAttachment, type CommentAuthor } from "@/stores/useTaskStore" +import { useTaskStore, Task, TaskType, TaskStatus, Priority, TaskAttachment } from "@/stores/useTaskStore" import { BacklogSkeleton, SearchSkeleton } from "@/components/LoadingSkeletons" import { Plus, MessageSquare, Calendar, Trash2, X, LayoutGrid, ListTodo, GripVertical, Paperclip, Download, Search, Archive } from "lucide-react" import { toast } from "sonner" @@ -422,27 +422,8 @@ export default function Home() { }) } - const getCommentAuthor = (value: unknown): CommentAuthor => { - if (value === "assistant") { - return { id: "assistant", name: "Assistant", type: "assistant" } - } - if (value === "user") { - return { id: "legacy-user", name: "User", type: "human" } - } - if (!value || typeof value !== "object") { - return { id: "legacy-user", name: "User", type: "human" } - } - - const candidate = value as Partial - const type = candidate.type === "assistant" || candidate.id === "assistant" ? "assistant" : "human" - return { - id: typeof candidate.id === "string" && candidate.id ? candidate.id : type === "assistant" ? "assistant" : "legacy-user", - name: typeof candidate.name === "string" && candidate.name ? candidate.name : type === "assistant" ? "Assistant" : "User", - email: typeof candidate.email === "string" && candidate.email ? candidate.email : undefined, - avatarUrl: typeof candidate.avatarUrl === "string" && candidate.avatarUrl ? candidate.avatarUrl : undefined, - type, - } - } + const getCommentAuthorId = (value: unknown): string | null => + typeof value === "string" && value.trim().length > 0 ? value.trim() : null const formatBytes = (bytes: number) => { if (!Number.isFinite(bytes) || bytes <= 0) return "0 B" @@ -872,7 +853,12 @@ export default function Home() { const handleAddComment = () => { if (newComment.trim() && selectedTaskId) { - addComment(selectedTaskId, newComment.trim()) + const commentAuthorId = getCommentAuthorId(currentUser.id) + if (!commentAuthorId) { + toast.error("You must be signed in to add a comment.") + return + } + addComment(selectedTaskId, newComment.trim(), commentAuthorId) setNewComment("") } } @@ -1697,10 +1683,15 @@ export default function Home() {

No comments yet. Add the first one.

) : ( editedTask.comments.map((comment) => { - const author = getCommentAuthor(comment.author) - const isAssistant = author.type === "assistant" - const displayName = author.id === currentUser.id ? "You" : author.name - const resolvedAuthorAvatar = author.avatarUrl || resolveAssignee(author.id)?.avatarUrl + const authorId = comment.commentAuthorId + const isAssistant = authorId === "assistant" + const resolvedAuthor = authorId === currentUser.id ? currentUser : resolveAssignee(authorId) + const displayName = isAssistant + ? "Assistant" + : authorId === currentUser.id + ? "You" + : resolvedAuthor?.name || "Unknown user" + const resolvedAuthorAvatar = resolvedAuthor?.avatarUrl return (
) : ( - + )}
diff --git a/src/app/tasks/[taskId]/page.tsx b/src/app/tasks/[taskId]/page.tsx index bd7f625..b2172ff 100644 --- a/src/app/tasks/[taskId]/page.tsx +++ b/src/app/tasks/[taskId]/page.tsx @@ -21,7 +21,6 @@ import { parseSprintStart } from "@/lib/utils" import { useTaskStore, type Comment as TaskComment, - type CommentAuthor, type Priority, type Task, type TaskAttachment, @@ -89,13 +88,15 @@ const getComments = (value: unknown): TaskComment[] => { for (const entry of value) { if (!entry || typeof entry !== "object") continue const comment = entry as Partial - if (typeof comment.id !== "string" || typeof comment.text !== "string") continue + if (typeof comment.id !== "string" || typeof comment.text !== "string" || typeof comment.createdAt !== "string") continue + const commentAuthorId = getCommentAuthorId(comment.commentAuthorId) + if (!commentAuthorId) continue normalized.push({ id: comment.id, text: comment.text, - createdAt: typeof comment.createdAt === "string" ? comment.createdAt : new Date().toISOString(), - author: getCommentAuthor(comment.author), + createdAt: comment.createdAt, + commentAuthorId, replies: getComments(comment.replies), }) } @@ -103,41 +104,17 @@ const getComments = (value: unknown): TaskComment[] => { return normalized } -const getCommentAuthor = (value: unknown): CommentAuthor => { - if (value === "assistant") { - return { id: "assistant", name: "Assistant", type: "assistant" } - } - if (value === "user") { - return { id: "legacy-user", name: "User", type: "human" } - } - if (!value || typeof value !== "object") { - return { id: "legacy-user", name: "User", type: "human" } - } +const getCommentAuthorId = (value: unknown): string | null => + typeof value === "string" && value.trim().length > 0 ? value.trim() : null - const candidate = value as Partial - const type = candidate.type === "assistant" || candidate.id === "assistant" ? "assistant" : "human" - return { - id: typeof candidate.id === "string" && candidate.id ? candidate.id : type === "assistant" ? "assistant" : "legacy-user", - name: typeof candidate.name === "string" && candidate.name ? candidate.name : type === "assistant" ? "Assistant" : "User", - email: typeof candidate.email === "string" && candidate.email ? candidate.email : undefined, - avatarUrl: typeof candidate.avatarUrl === "string" && candidate.avatarUrl ? candidate.avatarUrl : undefined, - type, - } -} +const getCurrentUserCommentAuthorId = (profile: UserProfile): string | null => + getCommentAuthorId(profile.id) -const profileToAuthor = (profile: UserProfile): CommentAuthor => ({ - id: profile.id, - name: profile.name, - email: profile.email, - avatarUrl: profile.avatarUrl, - type: "human", -}) - -const buildComment = (text: string, author: CommentAuthor): TaskComment => ({ +const buildComment = (text: string, commentAuthorId: string): TaskComment => ({ id: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`, text, createdAt: new Date().toISOString(), - author, + commentAuthorId, replies: [], }) @@ -400,10 +377,14 @@ export default function TaskDetailPage() { const handleAddComment = () => { if (!editedTask || !newComment.trim()) return - const actor = profileToAuthor(currentUser) + const commentAuthorId = getCurrentUserCommentAuthorId(currentUser) + if (!commentAuthorId) { + toast.error("You must be signed in to add a comment.") + return + } setEditedTask({ ...editedTask, - comments: [...getComments(editedTask.comments), buildComment(newComment.trim(), actor)], + comments: [...getComments(editedTask.comments), buildComment(newComment.trim(), commentAuthorId)], }) setNewComment("") } @@ -413,10 +394,14 @@ export default function TaskDetailPage() { const text = replyDrafts[parentId]?.trim() if (!text) return - const actor = profileToAuthor(currentUser) + const commentAuthorId = getCurrentUserCommentAuthorId(currentUser) + if (!commentAuthorId) { + toast.error("You must be signed in to reply.") + return + } setEditedTask({ ...editedTask, - comments: addReplyToThread(getComments(editedTask.comments), parentId, buildComment(text, actor)), + comments: addReplyToThread(getComments(editedTask.comments), parentId, buildComment(text, commentAuthorId)), }) setReplyDrafts((prev) => ({ ...prev, [parentId]: "" })) @@ -586,10 +571,11 @@ export default function TaskDetailPage() { const replies = getComments(comment.replies) const isReplying = !!openReplyEditors[comment.id] const replyDraft = replyDrafts[comment.id] || "" - const author = getCommentAuthor(comment.author) - const isAssistant = author.type === "assistant" - const displayName = isAssistant ? "Assistant" : author.id === currentUser.id ? "You" : author.name - const resolvedAuthorAvatar = author.avatarUrl || resolveAssignee(author.id)?.avatarUrl + const authorId = comment.commentAuthorId + const isAssistant = authorId === "assistant" + const resolvedAuthor = authorId === currentUser.id ? currentUser : resolveAssignee(authorId) + const displayName = isAssistant ? "Assistant" : authorId === currentUser.id ? "You" : resolvedAuthor?.name || "Unknown user" + const resolvedAuthorAvatar = resolvedAuthor?.avatarUrl return (
@@ -601,7 +587,7 @@ export default function TaskDetailPage() { AI ) : ( - + )} {displayName} {new Date(comment.createdAt).toLocaleString()} diff --git a/src/stores/useTaskStore.ts b/src/stores/useTaskStore.ts index c1df705..b87d5a4 100644 --- a/src/stores/useTaskStore.ts +++ b/src/stores/useTaskStore.ts @@ -22,18 +22,10 @@ export interface Comment { id: string text: string createdAt: string - author: CommentAuthor | 'user' | 'assistant' + commentAuthorId: string replies?: Comment[] } -export interface CommentAuthor { - id: string - name: string - email?: string - avatarUrl?: string - type: 'human' | 'assistant' -} - export interface UserProfile { id: string name: string @@ -121,7 +113,7 @@ interface TaskStore { getTasksBySprint: (sprintId: string) => Task[] // Comment actions - addComment: (taskId: string, text: string, author?: CommentAuthor | 'user' | 'assistant') => void + addComment: (taskId: string, text: string, commentAuthorId: string) => void deleteComment: (taskId: string, commentId: string) => void // Filters @@ -145,57 +137,14 @@ const normalizeUserProfile = (value: unknown, fallback: UserProfile = defaultCur return { id, name, email, avatarUrl } } -const profileToCommentAuthor = (profile: UserProfile): CommentAuthor => ({ +const profileToCommentAuthor = (profile: UserProfile) => ({ id: profile.id, name: profile.name, - email: profile.email, avatarUrl: profile.avatarUrl, - type: 'human', }) -const assistantAuthor: CommentAuthor = { - id: 'assistant', - name: 'Assistant', - type: 'assistant', -} - -const normalizeCommentAuthor = (value: unknown): CommentAuthor => { - if (value === 'assistant') return assistantAuthor - if (value === 'user') { - return { - id: 'legacy-user', - name: 'User', - type: 'human', - } - } - - if (!value || typeof value !== 'object') { - return { - id: 'legacy-user', - name: 'User', - type: 'human', - } - } - - const candidate = value as Partial - const type: CommentAuthor['type'] = - candidate.type === 'assistant' || candidate.id === 'assistant' ? 'assistant' : 'human' - - const id = typeof candidate.id === 'string' && candidate.id.trim().length > 0 - ? candidate.id - : type === 'assistant' - ? 'assistant' - : 'legacy-user' - const name = typeof candidate.name === 'string' && candidate.name.trim().length > 0 - ? candidate.name.trim() - : type === 'assistant' - ? 'Assistant' - : 'User' - const email = typeof candidate.email === 'string' && candidate.email.trim().length > 0 ? candidate.email.trim() : undefined - const avatarUrl = typeof candidate.avatarUrl === 'string' && candidate.avatarUrl.trim().length > 0 ? candidate.avatarUrl : undefined - - return { id, name, email, avatarUrl, type } -} +const normalizeCommentAuthorId = (value: unknown): string | null => + typeof value === 'string' && value.trim().length > 0 ? value.trim() : null const normalizeComments = (value: unknown): Comment[] => { if (!Array.isArray(value)) return [] @@ -205,13 +154,15 @@ const normalizeComments = (value: unknown): Comment[] => { for (const entry of value) { if (!entry || typeof entry !== 'object') continue const candidate = entry as Partial - if (typeof candidate.id !== 'string' || typeof candidate.text !== 'string') continue + if (typeof candidate.id !== 'string' || typeof candidate.text !== 'string' || typeof candidate.createdAt !== 'string') continue + const commentAuthorId = normalizeCommentAuthorId(candidate.commentAuthorId) + if (!commentAuthorId) continue comments.push({ id: candidate.id, text: candidate.text, - createdAt: typeof candidate.createdAt === 'string' ? candidate.createdAt : new Date().toISOString(), - author: normalizeCommentAuthor(candidate.author), + createdAt: candidate.createdAt, + commentAuthorId, replies: normalizeComments(candidate.replies), }) } @@ -646,13 +597,19 @@ export const useTaskStore = create()( return get().tasks.filter((t) => t.sprintId === sprintId) }, - addComment: (taskId, text, author) => { - const actor = normalizeCommentAuthor(author ?? profileToCommentAuthor(get().currentUser)) + addComment: (taskId, text, commentAuthorId) => { + const normalizedCommentAuthorId = normalizeCommentAuthorId(commentAuthorId) + if (!normalizedCommentAuthorId) { + const message = 'Failed to add comment: invalid comment author id' + console.error(message, { taskId, commentAuthorId }) + set({ syncError: message }) + return + } const newComment: Comment = { id: Date.now().toString(), text, createdAt: new Date().toISOString(), - author: actor, + commentAuthorId: normalizedCommentAuthorId, replies: [], } set((state) => { diff --git a/supabase/tasks.json b/supabase/tasks.json new file mode 100644 index 0000000..52981d4 --- /dev/null +++ b/supabase/tasks.json @@ -0,0 +1,1177 @@ +[ + { + "id": "33ebc71e-7d40-456c-8f98-bb3578d2bb2b", + "title": "RESEARCH: Find iOS side projects with MRR potential", + "description": "Research and identify iOS app ideas that have strong Monthly Recurring Revenue (MRR) opportunities. Create a md file and attach it here. \n\nAttach a file to this task when done", + "type": "research", + "status": "done", + "priority": "low", + "project_id": "a1b2c3d4-0003-0000-0000-000000000003", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-18 17:01:23.109+00", + "updated_at": "2026-02-21 23:11:20.567001+00", + "created_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "updated_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [], + "tags": [ + "ios", + "mrr", + "research", + "side-project", + "entrepreneurship", + "app-ideas" + ], + "attachments": [ + { + "id": "8227524b-9d03-407e-852a-911bd9c046f2", + "name": "ios-mrr-research-2026-02-21.md", + "size": 16491, + "type": "text/markdown", + "dataUrl": "data:text/markdown;base64,IyBpT1MgU3Vic2NyaXB0aW9uLUJhc2VkIFNpZGUgUHJvamVjdHMgd2l0aCBNUlIgUG90ZW50aWFsCioqUmVzZWFyY2ggRGF0ZToqKiBGZWJydWFyeSAyMSwgMjAyNiAgCioqRm9jdXM6KiogTW9udGhseSBSZWN1cnJpbmcgUmV2ZW51ZSAoTVJSKSBPcHBvcnR1bml0aWVzIGluIHRoZSBpT1MgQXBwIFN0b3JlCgotLS0KCiMjIEV4ZWN1dGl2ZSBTdW1tYXJ5CgpUaGUgaU9TIHN1YnNjcmlwdGlvbiBtb2RlbCBoYXMgbWF0dXJlZCBzaWduaWZpY2FudGx5LCB3aXRoIGNvbnN1bWVycyBpbmNyZWFzaW5nbHkgd2lsbGluZyB0byBwYXkgcmVjdXJyaW5nIGZlZXMgZm9yIGFwcHMgdGhhdCBwcm92aWRlIG9uZ29pbmcgdmFsdWUuIFRoZSBBcHAgU3RvcmUgZ2VuZXJhdGVkIGFwcHJveGltYXRlbHkgJDg1IGJpbGxpb24gaW4gY29uc3VtZXIgc3BlbmRpbmcgaW4gMjAyNCwgd2l0aCBzdWJzY3JpcHRpb24gcmV2ZW51ZSBjb250aW51aW5nIHRvIGdyb3cgYXQgMTUtMjAlIGFubnVhbGx5LiBUaGlzIHJlcG9ydCBpZGVudGlmaWVzIGhpZ2gtcG90ZW50aWFsIG5pY2hlcywgcHJvdmVuIG1vZGVscywgYW5kIHNwZWNpZmljIGFwcCBpZGVhcyB3aXRoIHN0cm9uZyBNUlIgdmlhYmlsaXR5LgoKIyMjIEtleSBNYXJrZXQgSW5zaWdodHM6Ci0gU3Vic2NyaXB0aW9uIGFwcHMgaGF2ZSAzLTV4IGhpZ2hlciBsaWZldGltZSB2YWx1ZSAoTFRWKSB0aGFuIHBhaWQgYXBwcwotIFRvcCBjYXRlZ29yaWVzOiBIZWFsdGggJiBGaXRuZXNzLCBQcm9kdWN0aXZpdHksIEVudGVydGFpbm1lbnQsIGFuZCBVdGlsaXRpZXMKLSBTd2VldCBzcG90IHByaWNpbmc6ICQ0Ljk5LSQ5Ljk5L21vbnRoIGZvciBjb25zdW1lciBhcHBzLCAkOS45OS0kMjkuOTkvbW9udGggZm9yIHByby9CMkIKLSBBdmVyYWdlIHN1YnNjcmlwdGlvbiByZXRlbnRpb24gYWZ0ZXIgMTIgbW9udGhzOiAyNS0zNSUgZm9yIHdlbGwtZGVzaWduZWQgYXBwcwoKLS0tCgojIyAxLiBIZWFsdGggJiBXZWxsbmVzcyBDYXRlZ29yeQoKIyMjIDEuMSBQZXJzb25hbGl6ZWQgU2xlZXAgT3B0aW1pemF0aW9uIEFwcAoqKkNvbmNlcHQ6KiogQUktcG93ZXJlZCBzbGVlcCBjb2FjaCB0aGF0IHRyYWNrcyBzbGVlcCBwYXR0ZXJucywgcHJvdmlkZXMgcGVyc29uYWxpemVkIHJlY29tbWVuZGF0aW9ucywgYW5kIGFkanVzdHMgYmFzZWQgb24gYmlvbWV0cmljcy4KCioqV2h5IE1SUiBQb3RlbnRpYWwgaXMgU3Ryb25nOioqCi0gU2xlZXAgbWFya2V0IHZhbHVlZCBhdCAkNjVCIGdsb2JhbGx5IGFuZCBncm93aW5nCi0gVXNlcnMgbmVlZCBvbmdvaW5nIGd1aWRhbmNlIChkYWlseSBzbGVlcCBkYXRhLCB3ZWVrbHkgcmVwb3J0cywgbW9udGhseSBpbnNpZ2h0cykKLSBIaWdoIHBlcmNlaXZlZCB2YWx1ZSAtIHBvb3Igc2xlZXAgYWZmZWN0cyBldmVyeXRoaW5nCi0gTmF0dXJhbCByZXRlbnRpb24gZHJpdmVyOiBwcm9ncmVzcyB0cmFja2luZyBvdmVyIHRpbWUKCioqUmV2ZW51ZSBNb2RlbDoqKgotIEZyZWUgdGllcjogQmFzaWMgc2xlZXAgdHJhY2tpbmcKLSBQcmVtaXVtOiAkNy45OS9tb250aCBvciAkNTkuOTkveWVhcgotIEFkZC1vbjogUGVyc29uYWxpemVkIHNsZWVwIHBsYW5zICgkMTkuOTkgb25lLXRpbWUpCgoqKk1hcmtldCBBbmFseXNpczoqKgotIENvbXBldGl0b3JzOiBTbGVlcCBDeWNsZSwgUGlsbG93LCBBdXRvU2xlZXAKLSBHYXA6IE1vc3QgYXBwcyB0cmFjayBidXQgZG9uJ3QgYWN0aXZlbHkgY29hY2gKLSBUYXJnZXQ6IDI1LTQ1IHllYXItb2xkIHByb2Zlc3Npb25hbHMgd2l0aCBkaXNwb3NhYmxlIGluY29tZQotIFRBTTogfjQwTSBwb3RlbnRpYWwgdXNlcnMgaW4gVVMgYWxvbmUKCioqSW1wbGVtZW50YXRpb24gQ29tcGxleGl0eToqKiA3LzEwCi0gSGVhbHRoS2l0IGludGVncmF0aW9uIGZvciBzbGVlcCBkYXRhCi0gTUwgbW9kZWwgZm9yIHBhdHRlcm4gcmVjb2duaXRpb24KLSBBdWRpbyBjb250ZW50IGxpYnJhcnkgKHNsZWVwIHNvdW5kcywgbWVkaXRhdGlvbnMpCi0gUmVxdWlyZXMgb25nb2luZyBjb250ZW50IGN1cmF0aW9uCgotLS0KCiMjIyAxLjIgTWljcm8tV29ya291dCAmIE1vYmlsaXR5IEFwcAoqKkNvbmNlcHQ6KiogNS0xNSBtaW51dGUgdGFyZ2V0ZWQgd29ya291dHMgZm9yIHNwZWNpZmljIGdvYWxzIChwb3N0dXJlLCBkZXNrLXdvcmtlciByZWxpZWYsIHByZS1zcG9ydCB3YXJtdXApIHdpdGggcHJvZ3Jlc3NpdmUgZGlmZmljdWx0eS4KCioqV2h5IE1SUiBQb3RlbnRpYWwgaXMgU3Ryb25nOioqCi0gVGltZS1zdHJhcHBlZCB1c2VycyBuZWVkIHF1aWNrLCBlZmZlY3RpdmUgc29sdXRpb25zCi0gUHJvZ3Jlc3NpdmUgcHJvZ3JhbXMgY3JlYXRlIG9uZ29pbmcgZW5nYWdlbWVudAotIENvcnBvcmF0ZSB3ZWxsbmVzcyBwYXJ0bmVyc2hpcHMgcG90ZW50aWFsCi0gTG93IGZyaWN0aW9uIGVudHJ5IHBvaW50CgoqKlJldmVudWUgTW9kZWw6KioKLSBGcmVlOiA1IGJhc2ljIHJvdXRpbmVzCi0gUHJlbWl1bTogJDkuOTkvbW9udGggb3IgJDc5Ljk5L3llYXIKLSBUZWFtL0NvcnBvcmF0ZTogJDUvdXNlci9tb250aAoKKipNYXJrZXQgQW5hbHlzaXM6KioKLSBDb21wZXRpdG9yczogU2V2ZW4sIFdha2VvdXQsIFN0cmV0Y2hpbmcgU2FtcGxlcgotIEdhcDogU3BlY2lhbGl6ZWQgcm91dGluZXMgZm9yIHNwZWNpZmljIHBhaW4gcG9pbnRzCi0gVGFyZ2V0OiBSZW1vdGUgd29ya2VycywgYXRobGV0ZXMsIGFnaW5nIHBvcHVsYXRpb24KLSBUQU06ICQxNC41QiBkaWdpdGFsIGZpdG5lc3MgbWFya2V0CgoqKkltcGxlbWVudGF0aW9uIENvbXBsZXhpdHk6KiogNi8xMAotIFZpZGVvIGNvbnRlbnQgbGlicmFyeQotIEN1c3RvbSB3b3Jrb3V0IGJ1aWxkZXIKLSBQcm9ncmVzcyB0cmFja2luZwotIEFwcGxlIFdhdGNoIGludGVncmF0aW9uCgotLS0KCiMjIDIuIFByb2R1Y3Rpdml0eSAmIFByb2Zlc3Npb25hbCBUb29scwoKIyMjIDIuMSBBSSBNZWV0aW5nIEFzc2lzdGFudCBmb3IgSW5kaXZpZHVhbHMKKipDb25jZXB0OioqIFBlcnNvbmFsIEFJIHRoYXQgam9pbnMgY2FsbHMgKHdpdGggcGVybWlzc2lvbiksIHRha2VzIG5vdGVzLCBjcmVhdGVzIGFjdGlvbiBpdGVtcywgYW5kIHRyYWNrcyBmb2xsb3ctdXBzIGFjcm9zcyBhbGwgbWVldGluZyBwbGF0Zm9ybXMuCgoqKldoeSBNUlIgUG90ZW50aWFsIGlzIFN0cm9uZzoqKgotIEtub3dsZWRnZSB3b3JrZXJzIGhhdmUgMTUrIGhvdXJzIG9mIG1lZXRpbmdzL3dlZWsKLSBIaWdoIHdpbGxpbmduZXNzIHRvIHBheSBmb3IgdGltZSBzYXZpbmdzCi0gQjJCMkMgcG90ZW50aWFsIChleHBlbnNlIHRocm91Z2ggY29tcGFuaWVzKQotIE5ldHdvcmsgZWZmZWN0cyBhcyB0ZWFtcyBhZG9wdAoKKipSZXZlbnVlIE1vZGVsOioqCi0gRnJlZTogNSBtZWV0aW5ncy9tb250aCwgYmFzaWMgdHJhbnNjcmlwdGlvbgotIFBybzogJDEyLjk5L21vbnRoIHVubGltaXRlZCBtZWV0aW5ncwotIFRlYW06ICQxOS45OS91c2VyL21vbnRoIHdpdGggY29sbGFib3JhdGlvbgoKKipNYXJrZXQgQW5hbHlzaXM6KioKLSBDb21wZXRpdG9yczogT3R0ZXIsIEZpcmVmbGllcywgR3JhaW4KLSBHYXA6IEluZGl2aWR1YWwtZm9jdXNlZCB2cyBlbnRlcnByaXNlIHRvb2xzCi0gVGFyZ2V0OiBDb25zdWx0YW50cywgZnJlZWxhbmNlcnMsIG1hbmFnZXJzCi0gVEFNOiAkMjBCKyBwcm9kdWN0aXZpdHkgc29mdHdhcmUgbWFya2V0CgoqKkltcGxlbWVudGF0aW9uIENvbXBsZXhpdHk6KiogOS8xMAotIEF1ZGlvIHByb2Nlc3NpbmcgYW5kIHRyYW5zY3JpcHRpb24KLSBBSSBzdW1tYXJpemF0aW9uIChyZXF1aXJlcyBMTE0gaW50ZWdyYXRpb24pCi0gQ2FsZW5kYXIgaW50ZWdyYXRpb25zCi0gRGF0YSBwcml2YWN5L3NlY3VyaXR5IGNvbnNpZGVyYXRpb25zCgotLS0KCiMjIyAyLjIgRm9jdXMgJiBEZWVwIFdvcmsgQ29tcGFuaW9uCioqQ29uY2VwdDoqKiBBZHZhbmNlZCBQb21vZG9yby90aW1lciBhcHAgd2l0aCBhY2NvdW50YWJpbGl0eSBmZWF0dXJlcywgZGlzdHJhY3Rpb24gYmxvY2tpbmcsIGFuYWx5dGljcywgYW5kIHRlYW0gY2hhbGxlbmdlcy4KCioqV2h5IE1SUiBQb3RlbnRpYWwgaXMgU3Ryb25nOioqCi0gQXR0ZW50aW9uIGVjb25vbXkgY3JlYXRlcyBkZW1hbmQgZm9yIGZvY3VzIHRvb2xzCi0gVGVhbXMvY29tcGFuaWVzIGJ1eSBmb3IgZW1wbG95ZWVzCi0gR2FtaWZpY2F0aW9uIGRyaXZlcyByZXRlbnRpb24KLSBEYXRhIGluc2lnaHRzIHByb3ZpZGUgb25nb2luZyB2YWx1ZQoKKipSZXZlbnVlIE1vZGVsOioqCi0gRnJlZTogQmFzaWMgdGltZXIgKyBsaW1pdGVkIHN0YXRzCi0gUHJvOiAkNC45OS9tb250aCBhZHZhbmNlZCBhbmFseXRpY3MKLSBUZWFtOiAkNi91c2VyL21vbnRoIHdpdGggbGVhZGVyYm9hcmRzCgoqKk1hcmtldCBBbmFseXNpczoqKgotIENvbXBldGl0b3JzOiBGb3Jlc3QsIEZyZWVkb20sIFJlc2N1ZVRpbWUKLSBHYXA6IEJldHRlciB0ZWFtIGZlYXR1cmVzICsgYWNjb3VudGFiaWxpdHkKLSBUYXJnZXQ6IFN0dWRlbnRzLCBkZXZlbG9wZXJzLCB3cml0ZXJzLCByZW1vdGUgdGVhbXMKLSBUQU06IDEwME0rIGtub3dsZWRnZSB3b3JrZXJzIGdsb2JhbGx5CgoqKkltcGxlbWVudGF0aW9uIENvbXBsZXhpdHk6KiogNS8xMAotIFRpbWVyIGVuZ2luZQotIFNjcmVlbiB0aW1lIEFQSSBpbnRlZ3JhdGlvbgotIFNvY2lhbCBmZWF0dXJlcwotIEFuYWx5dGljcyBkYXNoYm9hcmQKCi0tLQoKIyMgMy4gQ3JlYXRpdmUgJiBDb250ZW50IENyZWF0aW9uCgojIyMgMy4xIEFJLVBvd2VyZWQgQ29udGVudCBSZXB1cnBvc2luZwoqKkNvbmNlcHQ6KiogVGFrZSBvbmUgcGllY2Ugb2YgY29udGVudCAodmlkZW8sIHBvZGNhc3QsIGJsb2cpIGFuZCBhdXRvbWF0aWNhbGx5IGdlbmVyYXRlIHNvY2lhbCBjbGlwcywgcXVvdGVzLCB0aHVtYm5haWxzLCBhbmQgdmFyaWF0aW9ucy4KCioqV2h5IE1SUiBQb3RlbnRpYWwgaXMgU3Ryb25nOioqCi0gQ3JlYXRvciBlY29ub215IGlzIGJvb21pbmcgKCQyNTBCKykKLSBDb250ZW50IGNyZWF0aW9uIGlzIHRpbWUtaW50ZW5zaXZlCi0gQWdlbmNpZXMgaGF2ZSBoaWdoIHdpbGxpbmduZXNzIHRvIHBheQotIENvbnRpbnVvdXMgY29udGVudCBuZWVkcyA9IG9uZ29pbmcgc3Vic2NyaXB0aW9uCgoqKlJldmVudWUgTW9kZWw6KioKLSBGcmVlOiAzIHByb2plY3RzL21vbnRoLCB3YXRlcm1hcmtlZAotIENyZWF0b3I6ICQxOS45OS9tb250aCB1bmxpbWl0ZWQKLSBBZ2VuY3k6ICQ0OS45OS9tb250aCB0ZWFtIGZlYXR1cmVzCgoqKk1hcmtldCBBbmFseXNpczoqKgotIENvbXBldGl0b3JzOiBPcHVzIENsaXAsIERlc2NyaXB0LCBDYXBDdXQKLSBHYXA6IFNpbXBsaWZpZWQgaU9TLW5hdGl2ZSB3b3JrZmxvdwotIFRhcmdldDogU29sbyBjcmVhdG9ycywgc21hbGwgYWdlbmNpZXMKLSBUQU06IDUwTSsgY29udGVudCBjcmVhdG9ycwoKKipJbXBsZW1lbnRhdGlvbiBDb21wbGV4aXR5OioqIDgvMTAKLSBWaWRlby9hdWRpbyBwcm9jZXNzaW5nCi0gQUkgdHJhbnNjcmlwdGlvbiBhbmQgZWRpdGluZwotIFNvY2lhbCBwbGF0Zm9ybSBpbnRlZ3JhdGlvbnMKLSBDbG91ZCBwcm9jZXNzaW5nIGluZnJhc3RydWN0dXJlCgotLS0KCiMjIyAzLjIgVGVtcGxhdGUgTWFya2V0cGxhY2UgKyBFZGl0b3IKKipDb25jZXB0OioqIFByZW1pdW0gdGVtcGxhdGVzIGZvciBzb2NpYWwgcG9zdHMsIHByZXNlbnRhdGlvbnMsIHJlc3VtZXMsIG5ld3NsZXR0ZXJzIHdpdGggbmF0aXZlIGlPUyBlZGl0b3IuCgoqKldoeSBNUlIgUG90ZW50aWFsIGlzIFN0cm9uZzoqKgotIFRlbXBsYXRlIG1hcmtldCBpcyBtYXNzaXZlIGFuZCBldmVyZ3JlZW4KLSBSZWd1bGFyIG5ldyB0ZW1wbGF0ZSByZWxlYXNlcyBkcml2ZSByZXRlbnRpb24KLSBWaXN1YWwgY29udGVudCBuZWVkcyBhcmUgY29uc3RhbnQKLSBDYW4gdGFyZ2V0IG11bHRpcGxlIHZlcnRpY2FscwoKKipSZXZlbnVlIE1vZGVsOioqCi0gRnJlZTogNTAgYmFzaWMgdGVtcGxhdGVzCi0gUHJlbWl1bTogJDcuOTkvbW9udGggdW5saW1pdGVkICsgbmV3IHdlZWtseQotIENvbW1lcmNpYWw6ICQxOS45OS9tb250aCB3aXRoIGxpY2Vuc2luZwoKKipNYXJrZXQgQW5hbHlzaXM6KioKLSBDb21wZXRpdG9yczogQ2FudmEsIEFkb2JlIEV4cHJlc3MKLSBHYXA6IGlPUy1uYXRpdmUsIGNyZWF0b3ItZm9jdXNlZAotIFRhcmdldDogU21hbGwgYnVzaW5lc3Mgb3duZXJzLCBtYXJrZXRlcnMKLSBUQU06ICQzMEIrIGRlc2lnbiBzb2Z0d2FyZSBtYXJrZXQKCioqSW1wbGVtZW50YXRpb24gQ29tcGxleGl0eToqKiA2LzEwCi0gVGVtcGxhdGUgZW5naW5lCi0gQ3VzdG9tIGVkaXRvcgotIEFzc2V0IGxpYnJhcnkgbWFuYWdlbWVudAotIFJlZ3VsYXIgY29udGVudCB1cGRhdGVzCgotLS0KCiMjIDQuIFBlcnNvbmFsIEZpbmFuY2UgJiBXZWFsdGgKCiMjIyA0LjEgU3Vic2NyaXB0aW9uIE1hbmFnZXIgJiBPcHRpbWl6ZXIKKipDb25jZXB0OioqIFRyYWNrIGFsbCBzdWJzY3JpcHRpb25zLCBpZGVudGlmeSBzYXZpbmdzLCBjYW5jZWwgdW51c2VkIHNlcnZpY2VzLCBuZWdvdGlhdGUgYmlsbHMgYXV0b21hdGljYWxseS4KCioqV2h5IE1SUiBQb3RlbnRpYWwgaXMgU3Ryb25nOioqCi0gQXZlcmFnZSBwZXJzb24gaGFzIDEyKyBzdWJzY3JpcHRpb25zCi0gU2F2ZXMgdXNlcnMgcmVhbCBtb25leSAoanVzdGlmaWVzIGNvc3QpCi0gU3Vic2NyaXB0aW9uIGZhdGlndWUgaXMgcmVhbAotIFN0cm9uZyB3b3JkLW9mLW1vdXRoIHBvdGVudGlhbAoKKipSZXZlbnVlIE1vZGVsOioqCi0gRnJlZTogVHJhY2sgdXAgdG8gNSBzdWJzY3JpcHRpb25zCi0gUHJvOiAkNC45OS9tb250aCB1bmxpbWl0ZWQgKyBpbnNpZ2h0cwotIENvbmNpZXJnZTogJDkuOTkvbW9udGggaW5jbHVkZXMgYmlsbCBuZWdvdGlhdGlvbgoKKipNYXJrZXQgQW5hbHlzaXM6KioKLSBDb21wZXRpdG9yczogUm9ja2V0IE1vbmV5IChUcnVlYmlsbCksIFRyaW0KLSBHYXA6IFByaXZhY3ktZm9jdXNlZCwgaU9TLW5hdGl2ZSBzb2x1dGlvbgotIFRhcmdldDogMjUtNDUgYWdlIGdyb3VwIHdpdGggbXVsdGlwbGUgc3Vic2NyaXB0aW9ucwotIFRBTTogMjAwTSsgc3Vic2NyaXB0aW9uIHVzZXJzIGdsb2JhbGx5CgoqKkltcGxlbWVudGF0aW9uIENvbXBsZXhpdHk6KiogNi8xMAotIEJhbmsvY29ubmVjdCBpbnRlZ3JhdGlvbnMgKFBsYWlkKQotIFN1YnNjcmlwdGlvbiBkZXRlY3Rpb24gYWxnb3JpdGhtcwotIEVtYWlsIHBhcnNpbmcgZm9yIGJpbGxpbmcKLSBTZWN1cmUgY3JlZGVudGlhbCBoYW5kbGluZwoKLS0tCgojIyMgNC4yIE1pY3JvLUludmVzdGluZyBFZHVjYXRpb24gUGxhdGZvcm0KKipDb25jZXB0OioqIExlYXJuIGludmVzdGluZyB0aHJvdWdoIGJpdGUtc2l6ZWQgZGFpbHkgbGVzc29ucywgcGFwZXIgdHJhZGluZywgYW5kIGd1aWRlZCBwb3J0Zm9saW8gYnVpbGRpbmcuCgoqKldoeSBNUlIgUG90ZW50aWFsIGlzIFN0cm9uZzoqKgotIEZpbmFuY2lhbCBsaXRlcmFjeSBnYXAgaXMgaHVnZQotIEdhbWlmaWNhdGlvbiB3b3JrcyB3ZWxsIGZvciBsZWFybmluZwotIFVzZXJzIG5lZWQgb25nb2luZyBlZHVjYXRpb24KLSBBZmZpbGlhdGUgcmV2ZW51ZSBwb3RlbnRpYWwgZnJvbSBicm9rZXJzCgoqKlJldmVudWUgTW9kZWw6KioKLSBGcmVlOiBCYXNpYyBjb3Vyc2VzICsgcGFwZXIgdHJhZGluZwotIFByZW1pdW06ICQ4Ljk5L21vbnRoIGFkdmFuY2VkIGNvbnRlbnQKLSBQcm86ICQxOS45OS9tb250aCBpbmNsdWRlcyAxLW9uLTEgY29hY2hpbmcKCioqTWFya2V0IEFuYWx5c2lzOioqCi0gQ29tcGV0aXRvcnM6IER1b2xpbmdvLXN0eWxlIGFwcHMsIEZpZGVsaXR5LCBSb2Jpbmhvb2QKLSBHYXA6IEVkdWNhdGlvbi1maXJzdCBhcHByb2FjaCAobm90IHRyYWRpbmcpCi0gVGFyZ2V0OiAxOC0zNSBuZXcgaW52ZXN0b3JzCi0gVEFNOiAxMDBNKyBhc3BpcmluZyBpbnZlc3RvcnMKCioqSW1wbGVtZW50YXRpb24gQ29tcGxleGl0eToqKiA3LzEwCi0gRWR1Y2F0aW9uYWwgY29udGVudCBsaWJyYXJ5Ci0gUGFwZXIgdHJhZGluZyBzaW11bGF0aW9uCi0gUG9ydGZvbGlvIHRyYWNraW5nCi0gUHJvZ3Jlc3MgZ2FtaWZpY2F0aW9uCgotLS0KCiMjIDUuIFV0aWxpdGllcyAmIFRvb2xzCgojIyMgNS4xIEFkdmFuY2VkIEhhYml0IFRyYWNrZXIgd2l0aCBBY2NvdW50YWJpbGl0eQoqKkNvbmNlcHQ6KiogSGFiaXQgdHJhY2tpbmcgKyBhY2NvdW50YWJpbGl0eSBwYXJ0bmVycyArIGRhdGEgaW5zaWdodHMgKyBzdHJlYWsgY2hhbGxlbmdlcy4KCioqV2h5IE1SUiBQb3RlbnRpYWwgaXMgU3Ryb25nOioqCi0gSGFiaXQgZm9ybWF0aW9uIHJlcXVpcmVzIGxvbmctdGVybSBjb21taXRtZW50Ci0gU29jaWFsIGFjY291bnRhYmlsaXR5IGluY3JlYXNlcyByZXRlbnRpb24KLSBEYXRhIGluc2lnaHRzIGltcHJvdmUgb3ZlciB0aW1lCi0gQ29ycG9yYXRlIHdlbGxuZXNzIG1hcmtldAoKKipSZXZlbnVlIE1vZGVsOioqCi0gRnJlZTogMyBoYWJpdHMsIGJhc2ljIHRyYWNraW5nCi0gUHJlbWl1bTogJDUuOTkvbW9udGggdW5saW1pdGVkICsgaW5zaWdodHMKLSBUZWFtczogJDQvdXNlci9tb250aAoKKipNYXJrZXQgQW5hbHlzaXM6KioKLSBDb21wZXRpdG9yczogU3RyZWFrcywgSGFiaXRpZnksIERvbmUKLSBHYXA6IEJldHRlciBhY2NvdW50YWJpbGl0eSBmZWF0dXJlcwotIFRhcmdldDogR29hbC1vcmllbnRlZCBpbmRpdmlkdWFscwotIFRBTTogNTAwTSsgc21hcnRwaG9uZSB1c2VycyB3aXRoIGdvYWxzCgoqKkltcGxlbWVudGF0aW9uIENvbXBsZXhpdHk6KiogNS8xMAotIEhhYml0IHRyYWNraW5nIGVuZ2luZQotIFNvY2lhbCBmZWF0dXJlcwotIEFuYWx5dGljcwotIFdpZGdldHMgYW5kIGNvbXBsaWNhdGlvbnMKCi0tLQoKIyMjIDUuMiBEb2N1bWVudCBTY2FubmVyICsgT0NSICsgT3JnYW5pemF0aW9uCioqQ29uY2VwdDoqKiBTbWFydCBzY2FubmVyIHdpdGggQUkgY2F0ZWdvcml6YXRpb24sIHNlYXJjaGFibGUgUERGcywgZXhwZW5zZSB0cmFja2luZywgYW5kIGNsb3VkIHN5bmMuCgoqKldoeSBNUlIgUG90ZW50aWFsIGlzIFN0cm9uZzoqKgotIEV2ZXJ5b25lIHNjYW5zIGRvY3VtZW50cwotIE9DUiByZXF1aXJlcyBvbmdvaW5nIGltcHJvdmVtZW50Ci0gQnVzaW5lc3MgdXNlcnMgaGF2ZSBoaWdoIHdpbGxpbmduZXNzIHRvIHBheQotIEZyZXF1ZW50IHVzYWdlID0gaGlnaCByZXRlbnRpb24KCioqUmV2ZW51ZSBNb2RlbDoqKgotIEZyZWU6IDUwIHNjYW5zL21vbnRoLCBiYXNpYyBPQ1IKLSBQcm86ICQ3Ljk5L21vbnRoIHVubGltaXRlZCArIEFJIGZlYXR1cmVzCi0gQnVzaW5lc3M6ICQxNC45OS9tb250aCB0ZWFtIGZlYXR1cmVzCgoqKk1hcmtldCBBbmFseXNpczoqKgotIENvbXBldGl0b3JzOiBBZG9iZSBTY2FuLCBTY2FubmVyIFBybywgQ2FtU2Nhbm5lcgotIEdhcDogQmV0dGVyIEFJIG9yZ2FuaXphdGlvbiArIGV4cGVuc2UgdHJhY2tpbmcKLSBUYXJnZXQ6IFNtYWxsIGJ1c2luZXNzIG93bmVycywgY29udHJhY3RvcnMKLSBUQU06ICQxMEIrIGRvY3VtZW50IG1hbmFnZW1lbnQgbWFya2V0CgoqKkltcGxlbWVudGF0aW9uIENvbXBsZXhpdHk6KiogNi8xMAotIENhbWVyYS9kb2N1bWVudCBkZXRlY3Rpb24KLSBPQ1IgZW5naW5lIGludGVncmF0aW9uCi0gQUkgY2F0ZWdvcml6YXRpb24KLSBDbG91ZCBzeW5jIGluZnJhc3RydWN0dXJlCgotLS0KCiMjIDYuIFVuZGVyc2VydmVkIE5pY2hlcyB3aXRoIEhpZ2ggUG90ZW50aWFsCgojIyMgNi4xIFBldCBIZWFsdGggJiBDYXJlIFRyYWNrZXIKKipDb25jZXB0OioqIENvbXByZWhlbnNpdmUgcGV0IGhlYWx0aCB0cmFja2luZywgdmV0IGFwcG9pbnRtZW50IG1hbmFnZW1lbnQsIG1lZGljYXRpb24gcmVtaW5kZXJzLCBhbmQgYnJlZWQtc3BlY2lmaWMgY2FyZSB0aXBzLgoKKipXaHkgTVJSIFBvdGVudGlhbCBpcyBTdHJvbmc6KioKLSBQZXQgb3duZXJzIHNwZW5kICQxLDIwMCsveWVhciBwZXIgcGV0Ci0gSGVhbHRoIHRyYWNraW5nIHByZXZlbnRzIGNvc3RseSBlbWVyZ2VuY2llcwotIEVtb3Rpb25hbCBhdHRhY2htZW50IGRyaXZlcyByZXRlbnRpb24KLSBWZXQgaW50ZWdyYXRpb24gb3Bwb3J0dW5pdGllcwoKKipSZXZlbnVlIE1vZGVsOioqCi0gRnJlZTogMSBwZXQsIGJhc2ljIHRyYWNraW5nCi0gUHJlbWl1bTogJDUuOTkvbW9udGggdW5saW1pdGVkIHBldHMgKyBmZWF0dXJlcwotIFZldCBDb25uZWN0OiAkOS45OS9tb250aCBpbmNsdWRlcyB0ZWxlaGVhbHRoCgoqKk1hcmtldCBBbmFseXNpczoqKgotIENvbXBldGl0b3JzOiBQZXREZXNrLCAxMXBldHMKLSBHYXA6IENvbnN1bWVyLWZvY3VzZWQgdnMgdmV0LWZvY3VzZWQKLSBUYXJnZXQ6IDkwTSBwZXQtb3duaW5nIGhvdXNlaG9sZHMgaW4gVVMKLSBUQU06ICQxMzZCIHBldCBpbmR1c3RyeQoKKipJbXBsZW1lbnRhdGlvbiBDb21wbGV4aXR5OioqIDUvMTAKLSBQZXQgcHJvZmlsZXMgYW5kIGhlYWx0aCByZWNvcmRzCi0gUmVtaW5kZXIgc3lzdGVtCi0gQ29udGVudCBsaWJyYXJ5Ci0gUGhvdG8vZG9jdW1lbnQgc3RvcmFnZQoKLS0tCgojIyMgNi4yIFBsYW50IENhcmUgJiBHYXJkZW5pbmcgQXNzaXN0YW50CioqQ29uY2VwdDoqKiBQbGFudCBpZGVudGlmaWNhdGlvbiwgY2FyZSBzY2hlZHVsZXMsIGRpc2Vhc2UgZGlhZ25vc2lzLCBhbmQgZ2FyZGVuIHBsYW5uaW5nLgoKKipXaHkgTVJSIFBvdGVudGlhbCBpcyBTdHJvbmc6KioKLSBIb3VzZXBsYW50IGJvb20gY29udGludWVzCi0gUGxhbnRzIGRpZSB3aXRob3V0IGNhcmUgKG9uZ29pbmcgbmVlZCkKLSBTZWFzb25hbCBjb250ZW50IGtlZXBzIHVzZXJzIGVuZ2FnZWQKLSBHcm93aW5nIGdhcmRlbmluZyBkZW1vZ3JhcGhpYwoKKipSZXZlbnVlIE1vZGVsOioqCi0gRnJlZTogNSBwbGFudHMsIGJhc2ljIGNhcmUKLSBQcmVtaXVtOiAkNC45OS9tb250aCB1bmxpbWl0ZWQgKyBBSSBkaWFnbm9zaXMKLSBHYXJkZW4gUGxhbm5lcjogJDkuOTkvbW9udGggb3V0ZG9vciBmZWF0dXJlcwoKKipNYXJrZXQgQW5hbHlzaXM6KioKLSBDb21wZXRpdG9yczogUGxhbnRJbiwgUGljdHVyZVRoaXMsIFBsYW50YQotIEdhcDogQmV0dGVyIG91dGRvb3IgZ2FyZGVuIGZlYXR1cmVzCi0gVGFyZ2V0OiAzME0rIGhvdXNlcGxhbnQgb3duZXJzCi0gVEFNOiAkNTJCIGdhcmRlbmluZyBtYXJrZXQKCioqSW1wbGVtZW50YXRpb24gQ29tcGxleGl0eToqKiA2LzEwCi0gUGxhbnQgaWRlbnRpZmljYXRpb24gQUkKLSBDYXJlIHNjaGVkdWxpbmcKLSBQaG90byByZWNvZ25pdGlvbiBmb3IgZGlzZWFzZQotIENvbnRlbnQgbGlicmFyeQoKLS0tCgojIyMgNi4zIExhbmd1YWdlIExlYXJuaW5nIGZvciBTcGVjaWZpYyBQdXJwb3NlcwoqKkNvbmNlcHQ6KiogTGFuZ3VhZ2UgbGVhcm5pbmcgZm9jdXNlZCBvbiBzcGVjaWZpYyB1c2UgY2FzZXMgKHRyYXZlbCwgYnVzaW5lc3MsIGhlYWx0aGNhcmUgd29ya2VycykgcmF0aGVyIHRoYW4gZ2VuZXJhbCBmbHVlbmN5LgoKKipXaHkgTVJSIFBvdGVudGlhbCBpcyBTdHJvbmc6KioKLSBQcm9mZXNzaW9uYWwgbGFuZ3VhZ2UgbmVlZHMgYXJlIHVyZ2VudAotIFNwZWNpZmljIHZvY2FidWxhcnkgPSBmYXN0ZXIgcGVyY2VpdmVkIHZhbHVlCi0gQjJCIHRyYWluaW5nIGNvbnRyYWN0cyBwb3RlbnRpYWwKLSBIaWdoIG1vdGl2YXRpb24gbGVhcm5lcnMKCioqUmV2ZW51ZSBNb2RlbDoqKgotIEZyZWU6IEZpcnN0IGNoYXB0ZXIgb2YgZWFjaCBjb3Vyc2UKLSBQcmVtaXVtOiAkMTIuOTkvbW9udGggYWxsIGNvdXJzZXMKLSBFbnRlcnByaXNlOiBDdXN0b20gcHJpY2luZyBmb3Igb3JnYW5pemF0aW9ucwoKKipNYXJrZXQgQW5hbHlzaXM6KioKLSBDb21wZXRpdG9yczogRHVvbGluZ28sIEJhYmJlbCwgQnVzdXUKLSBHYXA6IFByb2Zlc3Npb24tc3BlY2lmaWMgY29udGVudAotIFRhcmdldDogSGVhbHRoY2FyZSB3b3JrZXJzLCBob3NwaXRhbGl0eSwgZXhwYXRzCi0gVEFNOiAkNjBCIGxhbmd1YWdlIGxlYXJuaW5nIG1hcmtldAoKKipJbXBsZW1lbnRhdGlvbiBDb21wbGV4aXR5OioqIDcvMTAKLSBTcGVjaWFsaXplZCBjb250ZW50IGNyZWF0aW9uCi0gU3BlZWNoIHJlY29nbml0aW9uCi0gU3BhY2VkIHJlcGV0aXRpb24KLSBQcm9ncmVzcyB0cmFja2luZwoKLS0tCgojIyA3LiBFbWVyZ2luZyBPcHBvcnR1bml0aWVzICgyMDI1LTIwMjYpCgojIyMgNy4xIEFJIENvbXBhbmlvbiBmb3IgU3BlY2lmaWMgTmljaGVzCioqQ29uY2VwdDoqKiBBSSBjb21wYW5pb25zIHRhaWxvcmVkIHRvIHNwZWNpZmljIG5lZWRzOiBlbGRlcmx5IGNvbXBhbmlvbnNoaXAsIEFESEQgY29hY2hpbmcsIHBhcmVudGluZyBzdXBwb3J0LCBncmllZiBjb3Vuc2VsaW5nLgoKKipXaHkgTVJSIFBvdGVudGlhbCBpcyBTdHJvbmc6KioKLSBMb25lbGluZXNzIGVwaWRlbWljCi0gTWVudGFsIGhlYWx0aCBzdXBwb3J0IHNob3J0YWdlCi0gMjQvNyBhdmFpbGFiaWxpdHkKLSBQZXJzb25hbGl6ZWQgc3VwcG9ydCBzY2FsZXMKCioqUmV2ZW51ZSBNb2RlbDoqKgotIEZyZWU6IExpbWl0ZWQgZGFpbHkgY29udmVyc2F0aW9ucwotIFByZW1pdW06ICQxNC45OS9tb250aCB1bmxpbWl0ZWQKLSBGYW1pbHk6ICQyNC45OS9tb250aCBtdWx0aXBsZSBwcm9maWxlcwoKKipNYXJrZXQgQW5hbHlzaXM6KioKLSBDb21wZXRpdG9yczogQ2hhcmFjdGVyLkFJLCBSZXBsaWthLCBXb2Vib3QKLSBHYXA6IFB1cnBvc2Utc3BlY2lmaWMsIHRoZXJhcGV1dGljIGZvY3VzCi0gVGFyZ2V0OiBWYXJpZXMgYnkgbmljaGUKLSBUQU06ICQ0NTBCKyBtZW50YWwgaGVhbHRoIG1hcmtldAoKKipJbXBsZW1lbnRhdGlvbiBDb21wbGV4aXR5OioqIDkvMTAKLSBMTE0gaW50ZWdyYXRpb24KLSBTYWZldHkvdGhlcmFwZXV0aWMgZ3VhcmRyYWlscwotIFBlcnNvbmFsaXphdGlvbiBlbmdpbmUKLSBDcmlzaXMgZGV0ZWN0aW9uCgotLS0KCiMjIyA3LjIgU3VzdGFpbmFibGUgTGl2aW5nIFRyYWNrZXIKKipDb25jZXB0OioqIFRyYWNrIGNhcmJvbiBmb290cHJpbnQsIGdldCBwZXJzb25hbGl6ZWQgcmVkdWN0aW9uIHRpcHMsIGNvbm5lY3Qgd2l0aCBsb2NhbCBzdXN0YWluYWJsZSBvcHRpb25zLgoKKipXaHkgTVJSIFBvdGVudGlhbCBpcyBTdHJvbmc6KioKLSBHcm93aW5nIGNsaW1hdGUgY29uc2Npb3VzbmVzcwotIEdhbWlmaWNhdGlvbiBwb3RlbnRpYWwKLSBCcmFuZCBwYXJ0bmVyc2hpcCBvcHBvcnR1bml0aWVzCi0gQ29ycG9yYXRlIEVTRyBhbGlnbm1lbnQKCioqUmV2ZW51ZSBNb2RlbDoqKgotIEZyZWU6IEJhc2ljIHRyYWNraW5nICsgdGlwcwotIFByZW1pdW06ICQ1Ljk5L21vbnRoIGFkdmFuY2VkIGluc2lnaHRzCi0gRW50ZXJwcmlzZTogRW1wbG95ZWUgc3VzdGFpbmFiaWxpdHkgcHJvZ3JhbXMKCioqTWFya2V0IEFuYWx5c2lzOioqCi0gQ29tcGV0aXRvcnM6IEpvcm8sIENvbW1vbnMsIEVhcnRoIEhlcm8KLSBHYXA6IGlPUy1uYXRpdmUsIGFjdGlvbmFibGUgcmVjb21tZW5kYXRpb25zCi0gVGFyZ2V0OiBFbnZpcm9ubWVudGFsbHkgY29uc2Npb3VzIDI1LTQ1Ci0gVEFNOiAkMTUwQisgc3VzdGFpbmFiaWxpdHkgbWFya2V0CgoqKkltcGxlbWVudGF0aW9uIENvbXBsZXhpdHk6KiogNi8xMAotIENhcmJvbiBjYWxjdWxhdGlvbiBhbGdvcml0aG1zCi0gU3BlbmRpbmcgZGF0YSBpbnRlZ3JhdGlvbgotIExvY2FsIGJ1c2luZXNzIGRhdGFiYXNlCi0gUHJvZ3Jlc3MgdHJhY2tpbmcKCi0tLQoKIyMgU3VtbWFyeSBUYWJsZTogVG9wIDEwIE1SUiBPcHBvcnR1bml0aWVzCgp8IFJhbmsgfCBBcHAgQ29uY2VwdCB8IE1vbnRobHkgUHJpY2UgfCBDb21wbGV4aXR5IHwgTVJSIFBvdGVudGlhbCB8CnwtLS0tLS18LS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLXwKfCAxIHwgQUkgTWVldGluZyBBc3Npc3RhbnQgfCAkMTIuOTkgfCA5LzEwIHwg4q2Q4q2Q4q2Q4q2Q4q2QIHwKfCAyIHwgQUkgQ29udGVudCBSZXB1cnBvc2luZyB8ICQxOS45OSB8IDgvMTAgfCDirZDirZDirZDirZDirZAgfAp8IDMgfCBQZXJzb25hbGl6ZWQgU2xlZXAgQ29hY2ggfCAkNy45OSB8IDcvMTAgfCDirZDirZDirZDirZDirZAgfAp8IDQgfCBNaWNyby1JbnZlc3RpbmcgRWR1Y2F0aW9uIHwgJDguOTkgfCA3LzEwIHwg4q2Q4q2Q4q2Q4q2QIHwKfCA1IHwgU3Vic2NyaXB0aW9uIE1hbmFnZXIgfCAkNC45OSB8IDYvMTAgfCDirZDirZDirZDirZAgfAp8IDYgfCBGb2N1cyAmIERlZXAgV29yayB8ICQ0Ljk5IHwgNS8xMCB8IOKtkOKtkOKtkOKtkCB8CnwgNyB8IFNtYXJ0IERvY3VtZW50IFNjYW5uZXIgfCAkNy45OSB8IDYvMTAgfCDirZDirZDirZDirZAgfAp8IDggfCBQZXQgSGVhbHRoIFRyYWNrZXIgfCAkNS45OSB8IDUvMTAgfCDirZDirZDirZAgfAp8IDkgfCBNaWNyby1Xb3Jrb3V0IEFwcCB8ICQ5Ljk5IHwgNi8xMCB8IOKtkOKtkOKtkOKtkCB8CnwgMTAgfCBBZHZhbmNlZCBIYWJpdCBUcmFja2VyIHwgJDUuOTkgfCA1LzEwIHwg4q2Q4q2Q4q2QIHwKCi0tLQoKIyMgSW1wbGVtZW50YXRpb24gUmVjb21tZW5kYXRpb25zCgojIyMgQmVzdCBTdGFydGluZyBQb2ludHMgKExvd2VyIENvbXBsZXhpdHksIEhpZ2ggTVJSKToKMS4gKipIYWJpdCBUcmFja2VyIHdpdGggQWNjb3VudGFiaWxpdHkqKiAoNS8xMCBjb21wbGV4aXR5KQoyLiAqKlBldCBIZWFsdGggVHJhY2tlcioqICg1LzEwIGNvbXBsZXhpdHkpCjMuICoqRm9jdXMgJiBEZWVwIFdvcmsgQXBwKiogKDUvMTAgY29tcGxleGl0eSkKNC4gKipEb2N1bWVudCBTY2FubmVyKiogKDYvMTAgY29tcGxleGl0eSkKCiMjIyBIaWdoZXN0IE1SUiBQb3RlbnRpYWwgKEhpZ2hlciBDb21wbGV4aXR5KToKMS4gKipBSSBNZWV0aW5nIEFzc2lzdGFudCoqIChtYXNzaXZlIFRBTSwgQjJCIHBvdGVudGlhbCkKMi4gKipDb250ZW50IFJlcHVycG9zaW5nIFRvb2wqKiAoY3JlYXRvciBlY29ub215IGJvb20pCjMuICoqU2xlZXAgT3B0aW1pemF0aW9uKiogKHJlY3VycmluZyBkYWlseSB2YWx1ZSkKCiMjIyBLZXkgU3VjY2VzcyBGYWN0b3JzOgotICoqRnJlZW1pdW0gbW9kZWwqKiB3b3JrcyBiZXN0IGZvciBpT1Mgc3Vic2NyaXB0aW9ucwotICoqRGFpbHkgdXNhZ2UgcGF0dGVybnMqKiBkcml2ZSByZXRlbnRpb24KLSAqKlByb2dyZXNzaXZlIHZhbHVlKiogb3ZlciB0aW1lIGp1c3RpZmllcyBvbmdvaW5nIHBheW1lbnQKLSAqKlRlYW0vY29ycG9yYXRlIGZlYXR1cmVzKiogZXhwYW5kIFRBTSBzaWduaWZpY2FudGx5Ci0gKipBcHBsZSBlY29zeXN0ZW0gaW50ZWdyYXRpb24qKiAoV2F0Y2gsIEhlYWx0aEtpdCwgU2hvcnRjdXRzKSBhZGRzIHZhbHVlCgotLS0KCiMjIEFwcCBTdG9yZSBPcHRpbWl6YXRpb24gTm90ZXMKCiMjIyBCZXN0IENhdGVnb3JpZXMgZm9yIFN1YnNjcmlwdGlvbnM6Ci0gSGVhbHRoICYgRml0bmVzcyAoIzEgZm9yIHN1YnNjcmlwdGlvbiByZXZlbnVlKQotIFByb2R1Y3Rpdml0eQotIFV0aWxpdGllcwotIEVkdWNhdGlvbgotIExpZmVzdHlsZQoKIyMjIFByaWNpbmcgUHN5Y2hvbG9neToKLSBBbm51YWwgcGxhbnMgc2hvdWxkIG9mZmVyIH40MCUgZGlzY291bnQgdnMgbW9udGhseQotIEZyZWUgdHJpYWxzIG9mIDctMTQgZGF5cyBjb252ZXJ0IGJlc3QKLSBGaXJzdC1tb250aCBkaXNjb3VudHMgY2FuIGRyaXZlIGFkb3B0aW9uCi0gRmFtaWx5IHBsYW5zIGluY3JlYXNlIExUViBieSAyLTN4CgojIyMgUmV0ZW50aW9uIEJlbmNobWFya3M6Ci0gTW9udGggMTogNjAtNzAlCi0gTW9udGggMzogMzUtNDUlCi0gTW9udGggMTI6IDI1LTM1JQotIEdvb2QgYXBwcyBhY2hpZXZlIDQwJSsgYW5udWFsIHJldGVudGlvbgoKLS0tCgojIyBDb25jbHVzaW9uCgpUaGUgaU9TIHN1YnNjcmlwdGlvbiBtYXJrZXQgcmVtYWlucyBoaWdobHkgdmlhYmxlIGZvciBzaWRlIHByb2plY3RzIHdpdGggdGhlIHJpZ2h0IGFwcHJvYWNoLiBUaGUga2V5IHRvIE1SUiBzdWNjZXNzIGlzIGNob29zaW5nIHByb2JsZW1zIHRoYXQgcmVxdWlyZSBvbmdvaW5nIHNvbHV0aW9ucywgcHJvdmlkaW5nIGNsZWFyIGRhaWx5L3dlZWtseSB2YWx1ZSwgYW5kIGJ1aWxkaW5nIGZlYXR1cmVzIHRoYXQgaW1wcm92ZSB3aXRoIGNvbnRpbnVlZCB1c2UuCgoqKlRvcCBSZWNvbW1lbmRhdGlvbnMgdG8gUHVyc3VlOioqCjEuIFN0YXJ0IHdpdGggKipIYWJpdCBUcmFja2VyKiogb3IgKipQZXQgSGVhbHRoKiogZm9yIGxvd2VyIGNvbXBsZXhpdHkKMi4gQ29uc2lkZXIgKipBSSBNZWV0aW5nIEFzc2lzdGFudCoqIGlmIHlvdSBoYXZlIHRlY2huaWNhbCByZXNvdXJjZXMKMy4gRXhwbG9yZSAqKlN1YnNjcmlwdGlvbiBNYW5hZ2VyKiogZm9yIGJyb2FkIGFwcGVhbAoKVGhlIG1hcmtldCByZXdhcmRzIGFwcHMgdGhhdCBzb2x2ZSBwZXJzaXN0ZW50IHByb2JsZW1zIHdpdGggZWxlZ2FuY2UgYW5kIG9uZ29pbmcgdmFsdWUuIEZvY3VzIG9uIHJldGVudGlvbiBmcm9tIGRheSBvbmXigJRhIDMwJSBhbm51YWwgcmV0ZW50aW9uIHJhdGUgd2l0aCBhICQ3Ljk5L21vbnRoIHByaWNlIHBvaW50IHlpZWxkcyB+JDMyIExUViBwZXIgY3VzdG9tZXIuIFdpdGggMSwwMDAgc3Vic2NyaWJlcnMsIHRoYXQncyAkMzJLIE1SUi4KCi0tLQoKKlJlcG9ydCBnZW5lcmF0ZWQgZm9yIGlPUyBNUlIgcmVzZWFyY2ggcHJvamVjdCoK", + "uploadedAt": "2026-02-21T22:53:20Z" + }, + { + "id": "0817027c-ab07-4c5a-8df5-2e18d134b9c7", + "name": "ios-mrr-research-2026-02-21.md", + "size": 16491, + "type": "text/markdown", + "dataUrl": "data:text/markdown;base64,IyBpT1MgU3Vic2NyaXB0aW9uLUJhc2VkIFNpZGUgUHJvamVjdHMgd2l0aCBNUlIgUG90ZW50aWFsCioqUmVzZWFyY2ggRGF0ZToqKiBGZWJydWFyeSAyMSwgMjAyNiAgCioqRm9jdXM6KiogTW9udGhseSBSZWN1cnJpbmcgUmV2ZW51ZSAoTVJSKSBPcHBvcnR1bml0aWVzIGluIHRoZSBpT1MgQXBwIFN0b3JlCgotLS0KCiMjIEV4ZWN1dGl2ZSBTdW1tYXJ5CgpUaGUgaU9TIHN1YnNjcmlwdGlvbiBtb2RlbCBoYXMgbWF0dXJlZCBzaWduaWZpY2FudGx5LCB3aXRoIGNvbnN1bWVycyBpbmNyZWFzaW5nbHkgd2lsbGluZyB0byBwYXkgcmVjdXJyaW5nIGZlZXMgZm9yIGFwcHMgdGhhdCBwcm92aWRlIG9uZ29pbmcgdmFsdWUuIFRoZSBBcHAgU3RvcmUgZ2VuZXJhdGVkIGFwcHJveGltYXRlbHkgJDg1IGJpbGxpb24gaW4gY29uc3VtZXIgc3BlbmRpbmcgaW4gMjAyNCwgd2l0aCBzdWJzY3JpcHRpb24gcmV2ZW51ZSBjb250aW51aW5nIHRvIGdyb3cgYXQgMTUtMjAlIGFubnVhbGx5LiBUaGlzIHJlcG9ydCBpZGVudGlmaWVzIGhpZ2gtcG90ZW50aWFsIG5pY2hlcywgcHJvdmVuIG1vZGVscywgYW5kIHNwZWNpZmljIGFwcCBpZGVhcyB3aXRoIHN0cm9uZyBNUlIgdmlhYmlsaXR5LgoKIyMjIEtleSBNYXJrZXQgSW5zaWdodHM6Ci0gU3Vic2NyaXB0aW9uIGFwcHMgaGF2ZSAzLTV4IGhpZ2hlciBsaWZldGltZSB2YWx1ZSAoTFRWKSB0aGFuIHBhaWQgYXBwcwotIFRvcCBjYXRlZ29yaWVzOiBIZWFsdGggJiBGaXRuZXNzLCBQcm9kdWN0aXZpdHksIEVudGVydGFpbm1lbnQsIGFuZCBVdGlsaXRpZXMKLSBTd2VldCBzcG90IHByaWNpbmc6ICQ0Ljk5LSQ5Ljk5L21vbnRoIGZvciBjb25zdW1lciBhcHBzLCAkOS45OS0kMjkuOTkvbW9udGggZm9yIHByby9CMkIKLSBBdmVyYWdlIHN1YnNjcmlwdGlvbiByZXRlbnRpb24gYWZ0ZXIgMTIgbW9udGhzOiAyNS0zNSUgZm9yIHdlbGwtZGVzaWduZWQgYXBwcwoKLS0tCgojIyAxLiBIZWFsdGggJiBXZWxsbmVzcyBDYXRlZ29yeQoKIyMjIDEuMSBQZXJzb25hbGl6ZWQgU2xlZXAgT3B0aW1pemF0aW9uIEFwcAoqKkNvbmNlcHQ6KiogQUktcG93ZXJlZCBzbGVlcCBjb2FjaCB0aGF0IHRyYWNrcyBzbGVlcCBwYXR0ZXJucywgcHJvdmlkZXMgcGVyc29uYWxpemVkIHJlY29tbWVuZGF0aW9ucywgYW5kIGFkanVzdHMgYmFzZWQgb24gYmlvbWV0cmljcy4KCioqV2h5IE1SUiBQb3RlbnRpYWwgaXMgU3Ryb25nOioqCi0gU2xlZXAgbWFya2V0IHZhbHVlZCBhdCAkNjVCIGdsb2JhbGx5IGFuZCBncm93aW5nCi0gVXNlcnMgbmVlZCBvbmdvaW5nIGd1aWRhbmNlIChkYWlseSBzbGVlcCBkYXRhLCB3ZWVrbHkgcmVwb3J0cywgbW9udGhseSBpbnNpZ2h0cykKLSBIaWdoIHBlcmNlaXZlZCB2YWx1ZSAtIHBvb3Igc2xlZXAgYWZmZWN0cyBldmVyeXRoaW5nCi0gTmF0dXJhbCByZXRlbnRpb24gZHJpdmVyOiBwcm9ncmVzcyB0cmFja2luZyBvdmVyIHRpbWUKCioqUmV2ZW51ZSBNb2RlbDoqKgotIEZyZWUgdGllcjogQmFzaWMgc2xlZXAgdHJhY2tpbmcKLSBQcmVtaXVtOiAkNy45OS9tb250aCBvciAkNTkuOTkveWVhcgotIEFkZC1vbjogUGVyc29uYWxpemVkIHNsZWVwIHBsYW5zICgkMTkuOTkgb25lLXRpbWUpCgoqKk1hcmtldCBBbmFseXNpczoqKgotIENvbXBldGl0b3JzOiBTbGVlcCBDeWNsZSwgUGlsbG93LCBBdXRvU2xlZXAKLSBHYXA6IE1vc3QgYXBwcyB0cmFjayBidXQgZG9uJ3QgYWN0aXZlbHkgY29hY2gKLSBUYXJnZXQ6IDI1LTQ1IHllYXItb2xkIHByb2Zlc3Npb25hbHMgd2l0aCBkaXNwb3NhYmxlIGluY29tZQotIFRBTTogfjQwTSBwb3RlbnRpYWwgdXNlcnMgaW4gVVMgYWxvbmUKCioqSW1wbGVtZW50YXRpb24gQ29tcGxleGl0eToqKiA3LzEwCi0gSGVhbHRoS2l0IGludGVncmF0aW9uIGZvciBzbGVlcCBkYXRhCi0gTUwgbW9kZWwgZm9yIHBhdHRlcm4gcmVjb2duaXRpb24KLSBBdWRpbyBjb250ZW50IGxpYnJhcnkgKHNsZWVwIHNvdW5kcywgbWVkaXRhdGlvbnMpCi0gUmVxdWlyZXMgb25nb2luZyBjb250ZW50IGN1cmF0aW9uCgotLS0KCiMjIyAxLjIgTWljcm8tV29ya291dCAmIE1vYmlsaXR5IEFwcAoqKkNvbmNlcHQ6KiogNS0xNSBtaW51dGUgdGFyZ2V0ZWQgd29ya291dHMgZm9yIHNwZWNpZmljIGdvYWxzIChwb3N0dXJlLCBkZXNrLXdvcmtlciByZWxpZWYsIHByZS1zcG9ydCB3YXJtdXApIHdpdGggcHJvZ3Jlc3NpdmUgZGlmZmljdWx0eS4KCioqV2h5IE1SUiBQb3RlbnRpYWwgaXMgU3Ryb25nOioqCi0gVGltZS1zdHJhcHBlZCB1c2VycyBuZWVkIHF1aWNrLCBlZmZlY3RpdmUgc29sdXRpb25zCi0gUHJvZ3Jlc3NpdmUgcHJvZ3JhbXMgY3JlYXRlIG9uZ29pbmcgZW5nYWdlbWVudAotIENvcnBvcmF0ZSB3ZWxsbmVzcyBwYXJ0bmVyc2hpcHMgcG90ZW50aWFsCi0gTG93IGZyaWN0aW9uIGVudHJ5IHBvaW50CgoqKlJldmVudWUgTW9kZWw6KioKLSBGcmVlOiA1IGJhc2ljIHJvdXRpbmVzCi0gUHJlbWl1bTogJDkuOTkvbW9udGggb3IgJDc5Ljk5L3llYXIKLSBUZWFtL0NvcnBvcmF0ZTogJDUvdXNlci9tb250aAoKKipNYXJrZXQgQW5hbHlzaXM6KioKLSBDb21wZXRpdG9yczogU2V2ZW4sIFdha2VvdXQsIFN0cmV0Y2hpbmcgU2FtcGxlcgotIEdhcDogU3BlY2lhbGl6ZWQgcm91dGluZXMgZm9yIHNwZWNpZmljIHBhaW4gcG9pbnRzCi0gVGFyZ2V0OiBSZW1vdGUgd29ya2VycywgYXRobGV0ZXMsIGFnaW5nIHBvcHVsYXRpb24KLSBUQU06ICQxNC41QiBkaWdpdGFsIGZpdG5lc3MgbWFya2V0CgoqKkltcGxlbWVudGF0aW9uIENvbXBsZXhpdHk6KiogNi8xMAotIFZpZGVvIGNvbnRlbnQgbGlicmFyeQotIEN1c3RvbSB3b3Jrb3V0IGJ1aWxkZXIKLSBQcm9ncmVzcyB0cmFja2luZwotIEFwcGxlIFdhdGNoIGludGVncmF0aW9uCgotLS0KCiMjIDIuIFByb2R1Y3Rpdml0eSAmIFByb2Zlc3Npb25hbCBUb29scwoKIyMjIDIuMSBBSSBNZWV0aW5nIEFzc2lzdGFudCBmb3IgSW5kaXZpZHVhbHMKKipDb25jZXB0OioqIFBlcnNvbmFsIEFJIHRoYXQgam9pbnMgY2FsbHMgKHdpdGggcGVybWlzc2lvbiksIHRha2VzIG5vdGVzLCBjcmVhdGVzIGFjdGlvbiBpdGVtcywgYW5kIHRyYWNrcyBmb2xsb3ctdXBzIGFjcm9zcyBhbGwgbWVldGluZyBwbGF0Zm9ybXMuCgoqKldoeSBNUlIgUG90ZW50aWFsIGlzIFN0cm9uZzoqKgotIEtub3dsZWRnZSB3b3JrZXJzIGhhdmUgMTUrIGhvdXJzIG9mIG1lZXRpbmdzL3dlZWsKLSBIaWdoIHdpbGxpbmduZXNzIHRvIHBheSBmb3IgdGltZSBzYXZpbmdzCi0gQjJCMkMgcG90ZW50aWFsIChleHBlbnNlIHRocm91Z2ggY29tcGFuaWVzKQotIE5ldHdvcmsgZWZmZWN0cyBhcyB0ZWFtcyBhZG9wdAoKKipSZXZlbnVlIE1vZGVsOioqCi0gRnJlZTogNSBtZWV0aW5ncy9tb250aCwgYmFzaWMgdHJhbnNjcmlwdGlvbgotIFBybzogJDEyLjk5L21vbnRoIHVubGltaXRlZCBtZWV0aW5ncwotIFRlYW06ICQxOS45OS91c2VyL21vbnRoIHdpdGggY29sbGFib3JhdGlvbgoKKipNYXJrZXQgQW5hbHlzaXM6KioKLSBDb21wZXRpdG9yczogT3R0ZXIsIEZpcmVmbGllcywgR3JhaW4KLSBHYXA6IEluZGl2aWR1YWwtZm9jdXNlZCB2cyBlbnRlcnByaXNlIHRvb2xzCi0gVGFyZ2V0OiBDb25zdWx0YW50cywgZnJlZWxhbmNlcnMsIG1hbmFnZXJzCi0gVEFNOiAkMjBCKyBwcm9kdWN0aXZpdHkgc29mdHdhcmUgbWFya2V0CgoqKkltcGxlbWVudGF0aW9uIENvbXBsZXhpdHk6KiogOS8xMAotIEF1ZGlvIHByb2Nlc3NpbmcgYW5kIHRyYW5zY3JpcHRpb24KLSBBSSBzdW1tYXJpemF0aW9uIChyZXF1aXJlcyBMTE0gaW50ZWdyYXRpb24pCi0gQ2FsZW5kYXIgaW50ZWdyYXRpb25zCi0gRGF0YSBwcml2YWN5L3NlY3VyaXR5IGNvbnNpZGVyYXRpb25zCgotLS0KCiMjIyAyLjIgRm9jdXMgJiBEZWVwIFdvcmsgQ29tcGFuaW9uCioqQ29uY2VwdDoqKiBBZHZhbmNlZCBQb21vZG9yby90aW1lciBhcHAgd2l0aCBhY2NvdW50YWJpbGl0eSBmZWF0dXJlcywgZGlzdHJhY3Rpb24gYmxvY2tpbmcsIGFuYWx5dGljcywgYW5kIHRlYW0gY2hhbGxlbmdlcy4KCioqV2h5IE1SUiBQb3RlbnRpYWwgaXMgU3Ryb25nOioqCi0gQXR0ZW50aW9uIGVjb25vbXkgY3JlYXRlcyBkZW1hbmQgZm9yIGZvY3VzIHRvb2xzCi0gVGVhbXMvY29tcGFuaWVzIGJ1eSBmb3IgZW1wbG95ZWVzCi0gR2FtaWZpY2F0aW9uIGRyaXZlcyByZXRlbnRpb24KLSBEYXRhIGluc2lnaHRzIHByb3ZpZGUgb25nb2luZyB2YWx1ZQoKKipSZXZlbnVlIE1vZGVsOioqCi0gRnJlZTogQmFzaWMgdGltZXIgKyBsaW1pdGVkIHN0YXRzCi0gUHJvOiAkNC45OS9tb250aCBhZHZhbmNlZCBhbmFseXRpY3MKLSBUZWFtOiAkNi91c2VyL21vbnRoIHdpdGggbGVhZGVyYm9hcmRzCgoqKk1hcmtldCBBbmFseXNpczoqKgotIENvbXBldGl0b3JzOiBGb3Jlc3QsIEZyZWVkb20sIFJlc2N1ZVRpbWUKLSBHYXA6IEJldHRlciB0ZWFtIGZlYXR1cmVzICsgYWNjb3VudGFiaWxpdHkKLSBUYXJnZXQ6IFN0dWRlbnRzLCBkZXZlbG9wZXJzLCB3cml0ZXJzLCByZW1vdGUgdGVhbXMKLSBUQU06IDEwME0rIGtub3dsZWRnZSB3b3JrZXJzIGdsb2JhbGx5CgoqKkltcGxlbWVudGF0aW9uIENvbXBsZXhpdHk6KiogNS8xMAotIFRpbWVyIGVuZ2luZQotIFNjcmVlbiB0aW1lIEFQSSBpbnRlZ3JhdGlvbgotIFNvY2lhbCBmZWF0dXJlcwotIEFuYWx5dGljcyBkYXNoYm9hcmQKCi0tLQoKIyMgMy4gQ3JlYXRpdmUgJiBDb250ZW50IENyZWF0aW9uCgojIyMgMy4xIEFJLVBvd2VyZWQgQ29udGVudCBSZXB1cnBvc2luZwoqKkNvbmNlcHQ6KiogVGFrZSBvbmUgcGllY2Ugb2YgY29udGVudCAodmlkZW8sIHBvZGNhc3QsIGJsb2cpIGFuZCBhdXRvbWF0aWNhbGx5IGdlbmVyYXRlIHNvY2lhbCBjbGlwcywgcXVvdGVzLCB0aHVtYm5haWxzLCBhbmQgdmFyaWF0aW9ucy4KCioqV2h5IE1SUiBQb3RlbnRpYWwgaXMgU3Ryb25nOioqCi0gQ3JlYXRvciBlY29ub215IGlzIGJvb21pbmcgKCQyNTBCKykKLSBDb250ZW50IGNyZWF0aW9uIGlzIHRpbWUtaW50ZW5zaXZlCi0gQWdlbmNpZXMgaGF2ZSBoaWdoIHdpbGxpbmduZXNzIHRvIHBheQotIENvbnRpbnVvdXMgY29udGVudCBuZWVkcyA9IG9uZ29pbmcgc3Vic2NyaXB0aW9uCgoqKlJldmVudWUgTW9kZWw6KioKLSBGcmVlOiAzIHByb2plY3RzL21vbnRoLCB3YXRlcm1hcmtlZAotIENyZWF0b3I6ICQxOS45OS9tb250aCB1bmxpbWl0ZWQKLSBBZ2VuY3k6ICQ0OS45OS9tb250aCB0ZWFtIGZlYXR1cmVzCgoqKk1hcmtldCBBbmFseXNpczoqKgotIENvbXBldGl0b3JzOiBPcHVzIENsaXAsIERlc2NyaXB0LCBDYXBDdXQKLSBHYXA6IFNpbXBsaWZpZWQgaU9TLW5hdGl2ZSB3b3JrZmxvdwotIFRhcmdldDogU29sbyBjcmVhdG9ycywgc21hbGwgYWdlbmNpZXMKLSBUQU06IDUwTSsgY29udGVudCBjcmVhdG9ycwoKKipJbXBsZW1lbnRhdGlvbiBDb21wbGV4aXR5OioqIDgvMTAKLSBWaWRlby9hdWRpbyBwcm9jZXNzaW5nCi0gQUkgdHJhbnNjcmlwdGlvbiBhbmQgZWRpdGluZwotIFNvY2lhbCBwbGF0Zm9ybSBpbnRlZ3JhdGlvbnMKLSBDbG91ZCBwcm9jZXNzaW5nIGluZnJhc3RydWN0dXJlCgotLS0KCiMjIyAzLjIgVGVtcGxhdGUgTWFya2V0cGxhY2UgKyBFZGl0b3IKKipDb25jZXB0OioqIFByZW1pdW0gdGVtcGxhdGVzIGZvciBzb2NpYWwgcG9zdHMsIHByZXNlbnRhdGlvbnMsIHJlc3VtZXMsIG5ld3NsZXR0ZXJzIHdpdGggbmF0aXZlIGlPUyBlZGl0b3IuCgoqKldoeSBNUlIgUG90ZW50aWFsIGlzIFN0cm9uZzoqKgotIFRlbXBsYXRlIG1hcmtldCBpcyBtYXNzaXZlIGFuZCBldmVyZ3JlZW4KLSBSZWd1bGFyIG5ldyB0ZW1wbGF0ZSByZWxlYXNlcyBkcml2ZSByZXRlbnRpb24KLSBWaXN1YWwgY29udGVudCBuZWVkcyBhcmUgY29uc3RhbnQKLSBDYW4gdGFyZ2V0IG11bHRpcGxlIHZlcnRpY2FscwoKKipSZXZlbnVlIE1vZGVsOioqCi0gRnJlZTogNTAgYmFzaWMgdGVtcGxhdGVzCi0gUHJlbWl1bTogJDcuOTkvbW9udGggdW5saW1pdGVkICsgbmV3IHdlZWtseQotIENvbW1lcmNpYWw6ICQxOS45OS9tb250aCB3aXRoIGxpY2Vuc2luZwoKKipNYXJrZXQgQW5hbHlzaXM6KioKLSBDb21wZXRpdG9yczogQ2FudmEsIEFkb2JlIEV4cHJlc3MKLSBHYXA6IGlPUy1uYXRpdmUsIGNyZWF0b3ItZm9jdXNlZAotIFRhcmdldDogU21hbGwgYnVzaW5lc3Mgb3duZXJzLCBtYXJrZXRlcnMKLSBUQU06ICQzMEIrIGRlc2lnbiBzb2Z0d2FyZSBtYXJrZXQKCioqSW1wbGVtZW50YXRpb24gQ29tcGxleGl0eToqKiA2LzEwCi0gVGVtcGxhdGUgZW5naW5lCi0gQ3VzdG9tIGVkaXRvcgotIEFzc2V0IGxpYnJhcnkgbWFuYWdlbWVudAotIFJlZ3VsYXIgY29udGVudCB1cGRhdGVzCgotLS0KCiMjIDQuIFBlcnNvbmFsIEZpbmFuY2UgJiBXZWFsdGgKCiMjIyA0LjEgU3Vic2NyaXB0aW9uIE1hbmFnZXIgJiBPcHRpbWl6ZXIKKipDb25jZXB0OioqIFRyYWNrIGFsbCBzdWJzY3JpcHRpb25zLCBpZGVudGlmeSBzYXZpbmdzLCBjYW5jZWwgdW51c2VkIHNlcnZpY2VzLCBuZWdvdGlhdGUgYmlsbHMgYXV0b21hdGljYWxseS4KCioqV2h5IE1SUiBQb3RlbnRpYWwgaXMgU3Ryb25nOioqCi0gQXZlcmFnZSBwZXJzb24gaGFzIDEyKyBzdWJzY3JpcHRpb25zCi0gU2F2ZXMgdXNlcnMgcmVhbCBtb25leSAoanVzdGlmaWVzIGNvc3QpCi0gU3Vic2NyaXB0aW9uIGZhdGlndWUgaXMgcmVhbAotIFN0cm9uZyB3b3JkLW9mLW1vdXRoIHBvdGVudGlhbAoKKipSZXZlbnVlIE1vZGVsOioqCi0gRnJlZTogVHJhY2sgdXAgdG8gNSBzdWJzY3JpcHRpb25zCi0gUHJvOiAkNC45OS9tb250aCB1bmxpbWl0ZWQgKyBpbnNpZ2h0cwotIENvbmNpZXJnZTogJDkuOTkvbW9udGggaW5jbHVkZXMgYmlsbCBuZWdvdGlhdGlvbgoKKipNYXJrZXQgQW5hbHlzaXM6KioKLSBDb21wZXRpdG9yczogUm9ja2V0IE1vbmV5IChUcnVlYmlsbCksIFRyaW0KLSBHYXA6IFByaXZhY3ktZm9jdXNlZCwgaU9TLW5hdGl2ZSBzb2x1dGlvbgotIFRhcmdldDogMjUtNDUgYWdlIGdyb3VwIHdpdGggbXVsdGlwbGUgc3Vic2NyaXB0aW9ucwotIFRBTTogMjAwTSsgc3Vic2NyaXB0aW9uIHVzZXJzIGdsb2JhbGx5CgoqKkltcGxlbWVudGF0aW9uIENvbXBsZXhpdHk6KiogNi8xMAotIEJhbmsvY29ubmVjdCBpbnRlZ3JhdGlvbnMgKFBsYWlkKQotIFN1YnNjcmlwdGlvbiBkZXRlY3Rpb24gYWxnb3JpdGhtcwotIEVtYWlsIHBhcnNpbmcgZm9yIGJpbGxpbmcKLSBTZWN1cmUgY3JlZGVudGlhbCBoYW5kbGluZwoKLS0tCgojIyMgNC4yIE1pY3JvLUludmVzdGluZyBFZHVjYXRpb24gUGxhdGZvcm0KKipDb25jZXB0OioqIExlYXJuIGludmVzdGluZyB0aHJvdWdoIGJpdGUtc2l6ZWQgZGFpbHkgbGVzc29ucywgcGFwZXIgdHJhZGluZywgYW5kIGd1aWRlZCBwb3J0Zm9saW8gYnVpbGRpbmcuCgoqKldoeSBNUlIgUG90ZW50aWFsIGlzIFN0cm9uZzoqKgotIEZpbmFuY2lhbCBsaXRlcmFjeSBnYXAgaXMgaHVnZQotIEdhbWlmaWNhdGlvbiB3b3JrcyB3ZWxsIGZvciBsZWFybmluZwotIFVzZXJzIG5lZWQgb25nb2luZyBlZHVjYXRpb24KLSBBZmZpbGlhdGUgcmV2ZW51ZSBwb3RlbnRpYWwgZnJvbSBicm9rZXJzCgoqKlJldmVudWUgTW9kZWw6KioKLSBGcmVlOiBCYXNpYyBjb3Vyc2VzICsgcGFwZXIgdHJhZGluZwotIFByZW1pdW06ICQ4Ljk5L21vbnRoIGFkdmFuY2VkIGNvbnRlbnQKLSBQcm86ICQxOS45OS9tb250aCBpbmNsdWRlcyAxLW9uLTEgY29hY2hpbmcKCioqTWFya2V0IEFuYWx5c2lzOioqCi0gQ29tcGV0aXRvcnM6IER1b2xpbmdvLXN0eWxlIGFwcHMsIEZpZGVsaXR5LCBSb2Jpbmhvb2QKLSBHYXA6IEVkdWNhdGlvbi1maXJzdCBhcHByb2FjaCAobm90IHRyYWRpbmcpCi0gVGFyZ2V0OiAxOC0zNSBuZXcgaW52ZXN0b3JzCi0gVEFNOiAxMDBNKyBhc3BpcmluZyBpbnZlc3RvcnMKCioqSW1wbGVtZW50YXRpb24gQ29tcGxleGl0eToqKiA3LzEwCi0gRWR1Y2F0aW9uYWwgY29udGVudCBsaWJyYXJ5Ci0gUGFwZXIgdHJhZGluZyBzaW11bGF0aW9uCi0gUG9ydGZvbGlvIHRyYWNraW5nCi0gUHJvZ3Jlc3MgZ2FtaWZpY2F0aW9uCgotLS0KCiMjIDUuIFV0aWxpdGllcyAmIFRvb2xzCgojIyMgNS4xIEFkdmFuY2VkIEhhYml0IFRyYWNrZXIgd2l0aCBBY2NvdW50YWJpbGl0eQoqKkNvbmNlcHQ6KiogSGFiaXQgdHJhY2tpbmcgKyBhY2NvdW50YWJpbGl0eSBwYXJ0bmVycyArIGRhdGEgaW5zaWdodHMgKyBzdHJlYWsgY2hhbGxlbmdlcy4KCioqV2h5IE1SUiBQb3RlbnRpYWwgaXMgU3Ryb25nOioqCi0gSGFiaXQgZm9ybWF0aW9uIHJlcXVpcmVzIGxvbmctdGVybSBjb21taXRtZW50Ci0gU29jaWFsIGFjY291bnRhYmlsaXR5IGluY3JlYXNlcyByZXRlbnRpb24KLSBEYXRhIGluc2lnaHRzIGltcHJvdmUgb3ZlciB0aW1lCi0gQ29ycG9yYXRlIHdlbGxuZXNzIG1hcmtldAoKKipSZXZlbnVlIE1vZGVsOioqCi0gRnJlZTogMyBoYWJpdHMsIGJhc2ljIHRyYWNraW5nCi0gUHJlbWl1bTogJDUuOTkvbW9udGggdW5saW1pdGVkICsgaW5zaWdodHMKLSBUZWFtczogJDQvdXNlci9tb250aAoKKipNYXJrZXQgQW5hbHlzaXM6KioKLSBDb21wZXRpdG9yczogU3RyZWFrcywgSGFiaXRpZnksIERvbmUKLSBHYXA6IEJldHRlciBhY2NvdW50YWJpbGl0eSBmZWF0dXJlcwotIFRhcmdldDogR29hbC1vcmllbnRlZCBpbmRpdmlkdWFscwotIFRBTTogNTAwTSsgc21hcnRwaG9uZSB1c2VycyB3aXRoIGdvYWxzCgoqKkltcGxlbWVudGF0aW9uIENvbXBsZXhpdHk6KiogNS8xMAotIEhhYml0IHRyYWNraW5nIGVuZ2luZQotIFNvY2lhbCBmZWF0dXJlcwotIEFuYWx5dGljcwotIFdpZGdldHMgYW5kIGNvbXBsaWNhdGlvbnMKCi0tLQoKIyMjIDUuMiBEb2N1bWVudCBTY2FubmVyICsgT0NSICsgT3JnYW5pemF0aW9uCioqQ29uY2VwdDoqKiBTbWFydCBzY2FubmVyIHdpdGggQUkgY2F0ZWdvcml6YXRpb24sIHNlYXJjaGFibGUgUERGcywgZXhwZW5zZSB0cmFja2luZywgYW5kIGNsb3VkIHN5bmMuCgoqKldoeSBNUlIgUG90ZW50aWFsIGlzIFN0cm9uZzoqKgotIEV2ZXJ5b25lIHNjYW5zIGRvY3VtZW50cwotIE9DUiByZXF1aXJlcyBvbmdvaW5nIGltcHJvdmVtZW50Ci0gQnVzaW5lc3MgdXNlcnMgaGF2ZSBoaWdoIHdpbGxpbmduZXNzIHRvIHBheQotIEZyZXF1ZW50IHVzYWdlID0gaGlnaCByZXRlbnRpb24KCioqUmV2ZW51ZSBNb2RlbDoqKgotIEZyZWU6IDUwIHNjYW5zL21vbnRoLCBiYXNpYyBPQ1IKLSBQcm86ICQ3Ljk5L21vbnRoIHVubGltaXRlZCArIEFJIGZlYXR1cmVzCi0gQnVzaW5lc3M6ICQxNC45OS9tb250aCB0ZWFtIGZlYXR1cmVzCgoqKk1hcmtldCBBbmFseXNpczoqKgotIENvbXBldGl0b3JzOiBBZG9iZSBTY2FuLCBTY2FubmVyIFBybywgQ2FtU2Nhbm5lcgotIEdhcDogQmV0dGVyIEFJIG9yZ2FuaXphdGlvbiArIGV4cGVuc2UgdHJhY2tpbmcKLSBUYXJnZXQ6IFNtYWxsIGJ1c2luZXNzIG93bmVycywgY29udHJhY3RvcnMKLSBUQU06ICQxMEIrIGRvY3VtZW50IG1hbmFnZW1lbnQgbWFya2V0CgoqKkltcGxlbWVudGF0aW9uIENvbXBsZXhpdHk6KiogNi8xMAotIENhbWVyYS9kb2N1bWVudCBkZXRlY3Rpb24KLSBPQ1IgZW5naW5lIGludGVncmF0aW9uCi0gQUkgY2F0ZWdvcml6YXRpb24KLSBDbG91ZCBzeW5jIGluZnJhc3RydWN0dXJlCgotLS0KCiMjIDYuIFVuZGVyc2VydmVkIE5pY2hlcyB3aXRoIEhpZ2ggUG90ZW50aWFsCgojIyMgNi4xIFBldCBIZWFsdGggJiBDYXJlIFRyYWNrZXIKKipDb25jZXB0OioqIENvbXByZWhlbnNpdmUgcGV0IGhlYWx0aCB0cmFja2luZywgdmV0IGFwcG9pbnRtZW50IG1hbmFnZW1lbnQsIG1lZGljYXRpb24gcmVtaW5kZXJzLCBhbmQgYnJlZWQtc3BlY2lmaWMgY2FyZSB0aXBzLgoKKipXaHkgTVJSIFBvdGVudGlhbCBpcyBTdHJvbmc6KioKLSBQZXQgb3duZXJzIHNwZW5kICQxLDIwMCsveWVhciBwZXIgcGV0Ci0gSGVhbHRoIHRyYWNraW5nIHByZXZlbnRzIGNvc3RseSBlbWVyZ2VuY2llcwotIEVtb3Rpb25hbCBhdHRhY2htZW50IGRyaXZlcyByZXRlbnRpb24KLSBWZXQgaW50ZWdyYXRpb24gb3Bwb3J0dW5pdGllcwoKKipSZXZlbnVlIE1vZGVsOioqCi0gRnJlZTogMSBwZXQsIGJhc2ljIHRyYWNraW5nCi0gUHJlbWl1bTogJDUuOTkvbW9udGggdW5saW1pdGVkIHBldHMgKyBmZWF0dXJlcwotIFZldCBDb25uZWN0OiAkOS45OS9tb250aCBpbmNsdWRlcyB0ZWxlaGVhbHRoCgoqKk1hcmtldCBBbmFseXNpczoqKgotIENvbXBldGl0b3JzOiBQZXREZXNrLCAxMXBldHMKLSBHYXA6IENvbnN1bWVyLWZvY3VzZWQgdnMgdmV0LWZvY3VzZWQKLSBUYXJnZXQ6IDkwTSBwZXQtb3duaW5nIGhvdXNlaG9sZHMgaW4gVVMKLSBUQU06ICQxMzZCIHBldCBpbmR1c3RyeQoKKipJbXBsZW1lbnRhdGlvbiBDb21wbGV4aXR5OioqIDUvMTAKLSBQZXQgcHJvZmlsZXMgYW5kIGhlYWx0aCByZWNvcmRzCi0gUmVtaW5kZXIgc3lzdGVtCi0gQ29udGVudCBsaWJyYXJ5Ci0gUGhvdG8vZG9jdW1lbnQgc3RvcmFnZQoKLS0tCgojIyMgNi4yIFBsYW50IENhcmUgJiBHYXJkZW5pbmcgQXNzaXN0YW50CioqQ29uY2VwdDoqKiBQbGFudCBpZGVudGlmaWNhdGlvbiwgY2FyZSBzY2hlZHVsZXMsIGRpc2Vhc2UgZGlhZ25vc2lzLCBhbmQgZ2FyZGVuIHBsYW5uaW5nLgoKKipXaHkgTVJSIFBvdGVudGlhbCBpcyBTdHJvbmc6KioKLSBIb3VzZXBsYW50IGJvb20gY29udGludWVzCi0gUGxhbnRzIGRpZSB3aXRob3V0IGNhcmUgKG9uZ29pbmcgbmVlZCkKLSBTZWFzb25hbCBjb250ZW50IGtlZXBzIHVzZXJzIGVuZ2FnZWQKLSBHcm93aW5nIGdhcmRlbmluZyBkZW1vZ3JhcGhpYwoKKipSZXZlbnVlIE1vZGVsOioqCi0gRnJlZTogNSBwbGFudHMsIGJhc2ljIGNhcmUKLSBQcmVtaXVtOiAkNC45OS9tb250aCB1bmxpbWl0ZWQgKyBBSSBkaWFnbm9zaXMKLSBHYXJkZW4gUGxhbm5lcjogJDkuOTkvbW9udGggb3V0ZG9vciBmZWF0dXJlcwoKKipNYXJrZXQgQW5hbHlzaXM6KioKLSBDb21wZXRpdG9yczogUGxhbnRJbiwgUGljdHVyZVRoaXMsIFBsYW50YQotIEdhcDogQmV0dGVyIG91dGRvb3IgZ2FyZGVuIGZlYXR1cmVzCi0gVGFyZ2V0OiAzME0rIGhvdXNlcGxhbnQgb3duZXJzCi0gVEFNOiAkNTJCIGdhcmRlbmluZyBtYXJrZXQKCioqSW1wbGVtZW50YXRpb24gQ29tcGxleGl0eToqKiA2LzEwCi0gUGxhbnQgaWRlbnRpZmljYXRpb24gQUkKLSBDYXJlIHNjaGVkdWxpbmcKLSBQaG90byByZWNvZ25pdGlvbiBmb3IgZGlzZWFzZQotIENvbnRlbnQgbGlicmFyeQoKLS0tCgojIyMgNi4zIExhbmd1YWdlIExlYXJuaW5nIGZvciBTcGVjaWZpYyBQdXJwb3NlcwoqKkNvbmNlcHQ6KiogTGFuZ3VhZ2UgbGVhcm5pbmcgZm9jdXNlZCBvbiBzcGVjaWZpYyB1c2UgY2FzZXMgKHRyYXZlbCwgYnVzaW5lc3MsIGhlYWx0aGNhcmUgd29ya2VycykgcmF0aGVyIHRoYW4gZ2VuZXJhbCBmbHVlbmN5LgoKKipXaHkgTVJSIFBvdGVudGlhbCBpcyBTdHJvbmc6KioKLSBQcm9mZXNzaW9uYWwgbGFuZ3VhZ2UgbmVlZHMgYXJlIHVyZ2VudAotIFNwZWNpZmljIHZvY2FidWxhcnkgPSBmYXN0ZXIgcGVyY2VpdmVkIHZhbHVlCi0gQjJCIHRyYWluaW5nIGNvbnRyYWN0cyBwb3RlbnRpYWwKLSBIaWdoIG1vdGl2YXRpb24gbGVhcm5lcnMKCioqUmV2ZW51ZSBNb2RlbDoqKgotIEZyZWU6IEZpcnN0IGNoYXB0ZXIgb2YgZWFjaCBjb3Vyc2UKLSBQcmVtaXVtOiAkMTIuOTkvbW9udGggYWxsIGNvdXJzZXMKLSBFbnRlcnByaXNlOiBDdXN0b20gcHJpY2luZyBmb3Igb3JnYW5pemF0aW9ucwoKKipNYXJrZXQgQW5hbHlzaXM6KioKLSBDb21wZXRpdG9yczogRHVvbGluZ28sIEJhYmJlbCwgQnVzdXUKLSBHYXA6IFByb2Zlc3Npb24tc3BlY2lmaWMgY29udGVudAotIFRhcmdldDogSGVhbHRoY2FyZSB3b3JrZXJzLCBob3NwaXRhbGl0eSwgZXhwYXRzCi0gVEFNOiAkNjBCIGxhbmd1YWdlIGxlYXJuaW5nIG1hcmtldAoKKipJbXBsZW1lbnRhdGlvbiBDb21wbGV4aXR5OioqIDcvMTAKLSBTcGVjaWFsaXplZCBjb250ZW50IGNyZWF0aW9uCi0gU3BlZWNoIHJlY29nbml0aW9uCi0gU3BhY2VkIHJlcGV0aXRpb24KLSBQcm9ncmVzcyB0cmFja2luZwoKLS0tCgojIyA3LiBFbWVyZ2luZyBPcHBvcnR1bml0aWVzICgyMDI1LTIwMjYpCgojIyMgNy4xIEFJIENvbXBhbmlvbiBmb3IgU3BlY2lmaWMgTmljaGVzCioqQ29uY2VwdDoqKiBBSSBjb21wYW5pb25zIHRhaWxvcmVkIHRvIHNwZWNpZmljIG5lZWRzOiBlbGRlcmx5IGNvbXBhbmlvbnNoaXAsIEFESEQgY29hY2hpbmcsIHBhcmVudGluZyBzdXBwb3J0LCBncmllZiBjb3Vuc2VsaW5nLgoKKipXaHkgTVJSIFBvdGVudGlhbCBpcyBTdHJvbmc6KioKLSBMb25lbGluZXNzIGVwaWRlbWljCi0gTWVudGFsIGhlYWx0aCBzdXBwb3J0IHNob3J0YWdlCi0gMjQvNyBhdmFpbGFiaWxpdHkKLSBQZXJzb25hbGl6ZWQgc3VwcG9ydCBzY2FsZXMKCioqUmV2ZW51ZSBNb2RlbDoqKgotIEZyZWU6IExpbWl0ZWQgZGFpbHkgY29udmVyc2F0aW9ucwotIFByZW1pdW06ICQxNC45OS9tb250aCB1bmxpbWl0ZWQKLSBGYW1pbHk6ICQyNC45OS9tb250aCBtdWx0aXBsZSBwcm9maWxlcwoKKipNYXJrZXQgQW5hbHlzaXM6KioKLSBDb21wZXRpdG9yczogQ2hhcmFjdGVyLkFJLCBSZXBsaWthLCBXb2Vib3QKLSBHYXA6IFB1cnBvc2Utc3BlY2lmaWMsIHRoZXJhcGV1dGljIGZvY3VzCi0gVGFyZ2V0OiBWYXJpZXMgYnkgbmljaGUKLSBUQU06ICQ0NTBCKyBtZW50YWwgaGVhbHRoIG1hcmtldAoKKipJbXBsZW1lbnRhdGlvbiBDb21wbGV4aXR5OioqIDkvMTAKLSBMTE0gaW50ZWdyYXRpb24KLSBTYWZldHkvdGhlcmFwZXV0aWMgZ3VhcmRyYWlscwotIFBlcnNvbmFsaXphdGlvbiBlbmdpbmUKLSBDcmlzaXMgZGV0ZWN0aW9uCgotLS0KCiMjIyA3LjIgU3VzdGFpbmFibGUgTGl2aW5nIFRyYWNrZXIKKipDb25jZXB0OioqIFRyYWNrIGNhcmJvbiBmb290cHJpbnQsIGdldCBwZXJzb25hbGl6ZWQgcmVkdWN0aW9uIHRpcHMsIGNvbm5lY3Qgd2l0aCBsb2NhbCBzdXN0YWluYWJsZSBvcHRpb25zLgoKKipXaHkgTVJSIFBvdGVudGlhbCBpcyBTdHJvbmc6KioKLSBHcm93aW5nIGNsaW1hdGUgY29uc2Npb3VzbmVzcwotIEdhbWlmaWNhdGlvbiBwb3RlbnRpYWwKLSBCcmFuZCBwYXJ0bmVyc2hpcCBvcHBvcnR1bml0aWVzCi0gQ29ycG9yYXRlIEVTRyBhbGlnbm1lbnQKCioqUmV2ZW51ZSBNb2RlbDoqKgotIEZyZWU6IEJhc2ljIHRyYWNraW5nICsgdGlwcwotIFByZW1pdW06ICQ1Ljk5L21vbnRoIGFkdmFuY2VkIGluc2lnaHRzCi0gRW50ZXJwcmlzZTogRW1wbG95ZWUgc3VzdGFpbmFiaWxpdHkgcHJvZ3JhbXMKCioqTWFya2V0IEFuYWx5c2lzOioqCi0gQ29tcGV0aXRvcnM6IEpvcm8sIENvbW1vbnMsIEVhcnRoIEhlcm8KLSBHYXA6IGlPUy1uYXRpdmUsIGFjdGlvbmFibGUgcmVjb21tZW5kYXRpb25zCi0gVGFyZ2V0OiBFbnZpcm9ubWVudGFsbHkgY29uc2Npb3VzIDI1LTQ1Ci0gVEFNOiAkMTUwQisgc3VzdGFpbmFiaWxpdHkgbWFya2V0CgoqKkltcGxlbWVudGF0aW9uIENvbXBsZXhpdHk6KiogNi8xMAotIENhcmJvbiBjYWxjdWxhdGlvbiBhbGdvcml0aG1zCi0gU3BlbmRpbmcgZGF0YSBpbnRlZ3JhdGlvbgotIExvY2FsIGJ1c2luZXNzIGRhdGFiYXNlCi0gUHJvZ3Jlc3MgdHJhY2tpbmcKCi0tLQoKIyMgU3VtbWFyeSBUYWJsZTogVG9wIDEwIE1SUiBPcHBvcnR1bml0aWVzCgp8IFJhbmsgfCBBcHAgQ29uY2VwdCB8IE1vbnRobHkgUHJpY2UgfCBDb21wbGV4aXR5IHwgTVJSIFBvdGVudGlhbCB8CnwtLS0tLS18LS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLXwKfCAxIHwgQUkgTWVldGluZyBBc3Npc3RhbnQgfCAkMTIuOTkgfCA5LzEwIHwg4q2Q4q2Q4q2Q4q2Q4q2QIHwKfCAyIHwgQUkgQ29udGVudCBSZXB1cnBvc2luZyB8ICQxOS45OSB8IDgvMTAgfCDirZDirZDirZDirZDirZAgfAp8IDMgfCBQZXJzb25hbGl6ZWQgU2xlZXAgQ29hY2ggfCAkNy45OSB8IDcvMTAgfCDirZDirZDirZDirZDirZAgfAp8IDQgfCBNaWNyby1JbnZlc3RpbmcgRWR1Y2F0aW9uIHwgJDguOTkgfCA3LzEwIHwg4q2Q4q2Q4q2Q4q2QIHwKfCA1IHwgU3Vic2NyaXB0aW9uIE1hbmFnZXIgfCAkNC45OSB8IDYvMTAgfCDirZDirZDirZDirZAgfAp8IDYgfCBGb2N1cyAmIERlZXAgV29yayB8ICQ0Ljk5IHwgNS8xMCB8IOKtkOKtkOKtkOKtkCB8CnwgNyB8IFNtYXJ0IERvY3VtZW50IFNjYW5uZXIgfCAkNy45OSB8IDYvMTAgfCDirZDirZDirZDirZAgfAp8IDggfCBQZXQgSGVhbHRoIFRyYWNrZXIgfCAkNS45OSB8IDUvMTAgfCDirZDirZDirZAgfAp8IDkgfCBNaWNyby1Xb3Jrb3V0IEFwcCB8ICQ5Ljk5IHwgNi8xMCB8IOKtkOKtkOKtkOKtkCB8CnwgMTAgfCBBZHZhbmNlZCBIYWJpdCBUcmFja2VyIHwgJDUuOTkgfCA1LzEwIHwg4q2Q4q2Q4q2QIHwKCi0tLQoKIyMgSW1wbGVtZW50YXRpb24gUmVjb21tZW5kYXRpb25zCgojIyMgQmVzdCBTdGFydGluZyBQb2ludHMgKExvd2VyIENvbXBsZXhpdHksIEhpZ2ggTVJSKToKMS4gKipIYWJpdCBUcmFja2VyIHdpdGggQWNjb3VudGFiaWxpdHkqKiAoNS8xMCBjb21wbGV4aXR5KQoyLiAqKlBldCBIZWFsdGggVHJhY2tlcioqICg1LzEwIGNvbXBsZXhpdHkpCjMuICoqRm9jdXMgJiBEZWVwIFdvcmsgQXBwKiogKDUvMTAgY29tcGxleGl0eSkKNC4gKipEb2N1bWVudCBTY2FubmVyKiogKDYvMTAgY29tcGxleGl0eSkKCiMjIyBIaWdoZXN0IE1SUiBQb3RlbnRpYWwgKEhpZ2hlciBDb21wbGV4aXR5KToKMS4gKipBSSBNZWV0aW5nIEFzc2lzdGFudCoqIChtYXNzaXZlIFRBTSwgQjJCIHBvdGVudGlhbCkKMi4gKipDb250ZW50IFJlcHVycG9zaW5nIFRvb2wqKiAoY3JlYXRvciBlY29ub215IGJvb20pCjMuICoqU2xlZXAgT3B0aW1pemF0aW9uKiogKHJlY3VycmluZyBkYWlseSB2YWx1ZSkKCiMjIyBLZXkgU3VjY2VzcyBGYWN0b3JzOgotICoqRnJlZW1pdW0gbW9kZWwqKiB3b3JrcyBiZXN0IGZvciBpT1Mgc3Vic2NyaXB0aW9ucwotICoqRGFpbHkgdXNhZ2UgcGF0dGVybnMqKiBkcml2ZSByZXRlbnRpb24KLSAqKlByb2dyZXNzaXZlIHZhbHVlKiogb3ZlciB0aW1lIGp1c3RpZmllcyBvbmdvaW5nIHBheW1lbnQKLSAqKlRlYW0vY29ycG9yYXRlIGZlYXR1cmVzKiogZXhwYW5kIFRBTSBzaWduaWZpY2FudGx5Ci0gKipBcHBsZSBlY29zeXN0ZW0gaW50ZWdyYXRpb24qKiAoV2F0Y2gsIEhlYWx0aEtpdCwgU2hvcnRjdXRzKSBhZGRzIHZhbHVlCgotLS0KCiMjIEFwcCBTdG9yZSBPcHRpbWl6YXRpb24gTm90ZXMKCiMjIyBCZXN0IENhdGVnb3JpZXMgZm9yIFN1YnNjcmlwdGlvbnM6Ci0gSGVhbHRoICYgRml0bmVzcyAoIzEgZm9yIHN1YnNjcmlwdGlvbiByZXZlbnVlKQotIFByb2R1Y3Rpdml0eQotIFV0aWxpdGllcwotIEVkdWNhdGlvbgotIExpZmVzdHlsZQoKIyMjIFByaWNpbmcgUHN5Y2hvbG9neToKLSBBbm51YWwgcGxhbnMgc2hvdWxkIG9mZmVyIH40MCUgZGlzY291bnQgdnMgbW9udGhseQotIEZyZWUgdHJpYWxzIG9mIDctMTQgZGF5cyBjb252ZXJ0IGJlc3QKLSBGaXJzdC1tb250aCBkaXNjb3VudHMgY2FuIGRyaXZlIGFkb3B0aW9uCi0gRmFtaWx5IHBsYW5zIGluY3JlYXNlIExUViBieSAyLTN4CgojIyMgUmV0ZW50aW9uIEJlbmNobWFya3M6Ci0gTW9udGggMTogNjAtNzAlCi0gTW9udGggMzogMzUtNDUlCi0gTW9udGggMTI6IDI1LTM1JQotIEdvb2QgYXBwcyBhY2hpZXZlIDQwJSsgYW5udWFsIHJldGVudGlvbgoKLS0tCgojIyBDb25jbHVzaW9uCgpUaGUgaU9TIHN1YnNjcmlwdGlvbiBtYXJrZXQgcmVtYWlucyBoaWdobHkgdmlhYmxlIGZvciBzaWRlIHByb2plY3RzIHdpdGggdGhlIHJpZ2h0IGFwcHJvYWNoLiBUaGUga2V5IHRvIE1SUiBzdWNjZXNzIGlzIGNob29zaW5nIHByb2JsZW1zIHRoYXQgcmVxdWlyZSBvbmdvaW5nIHNvbHV0aW9ucywgcHJvdmlkaW5nIGNsZWFyIGRhaWx5L3dlZWtseSB2YWx1ZSwgYW5kIGJ1aWxkaW5nIGZlYXR1cmVzIHRoYXQgaW1wcm92ZSB3aXRoIGNvbnRpbnVlZCB1c2UuCgoqKlRvcCBSZWNvbW1lbmRhdGlvbnMgdG8gUHVyc3VlOioqCjEuIFN0YXJ0IHdpdGggKipIYWJpdCBUcmFja2VyKiogb3IgKipQZXQgSGVhbHRoKiogZm9yIGxvd2VyIGNvbXBsZXhpdHkKMi4gQ29uc2lkZXIgKipBSSBNZWV0aW5nIEFzc2lzdGFudCoqIGlmIHlvdSBoYXZlIHRlY2huaWNhbCByZXNvdXJjZXMKMy4gRXhwbG9yZSAqKlN1YnNjcmlwdGlvbiBNYW5hZ2VyKiogZm9yIGJyb2FkIGFwcGVhbAoKVGhlIG1hcmtldCByZXdhcmRzIGFwcHMgdGhhdCBzb2x2ZSBwZXJzaXN0ZW50IHByb2JsZW1zIHdpdGggZWxlZ2FuY2UgYW5kIG9uZ29pbmcgdmFsdWUuIEZvY3VzIG9uIHJldGVudGlvbiBmcm9tIGRheSBvbmXigJRhIDMwJSBhbm51YWwgcmV0ZW50aW9uIHJhdGUgd2l0aCBhICQ3Ljk5L21vbnRoIHByaWNlIHBvaW50IHlpZWxkcyB+JDMyIExUViBwZXIgY3VzdG9tZXIuIFdpdGggMSwwMDAgc3Vic2NyaWJlcnMsIHRoYXQncyAkMzJLIE1SUi4KCi0tLQoKKlJlcG9ydCBnZW5lcmF0ZWQgZm9yIGlPUyBNUlIgcmVzZWFyY2ggcHJvamVjdCoK", + "uploadedAt": "2026-02-21T23:11:19Z" + } + ] + }, + { + "id": "0da220bc-eb6b-4be1-846a-c2c801def427", + "title": "Gantt Board", + "description": "When editing the task, you click the Save at the bottom right and you have no idea what happened, if it failed or saved or what?", + "type": "task", + "status": "done", + "priority": "urgent", + "project_id": "a1b2c3d4-0001-0000-0000-000000000001", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-21 22:10:23.675+00", + "updated_at": "2026-02-21 23:13:32.420417+00", + "created_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "updated_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [], + "tags": [], + "attachments": [] + }, + { + "id": "12780467-db89-4b0d-bca5-422be441aee5", + "title": "Blog - Backup", + "description": "Add CLI/Scripts as noted in your workflow", + "type": "task", + "status": "done", + "priority": "high", + "project_id": "a1b2c3d4-0001-0000-0000-000000000001", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-21 23:32:20.163+00", + "updated_at": "2026-02-22 05:19:46.641824+00", + "created_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "updated_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [], + "tags": [], + "attachments": [] + }, + { + "id": "1cd602eb-20dc-4d59-8581-cffbecb2586e", + "title": "Apply Voxyz Autonomous Architecture to Mission Control Phase 10", + "description": null, + "type": "task", + "status": "review", + "priority": "medium", + "project_id": "a1b2c3d4-0002-0000-0000-000000000002", + "sprint_id": "b2c3d4e5-0002-0000-0000-000000000002", + "created_at": "2026-02-23 00:10:51.900762+00", + "updated_at": "2026-02-23 17:32:37.86652+00", + "created_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "updated_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [], + "tags": [ + "mission-control", + "phase-10", + "automation", + "ai-agents", + "voxyz", + "research-application" + ], + "attachments": [] + }, + { + "id": "42218ed3-55bb-4bd6-97e0-7b9b39f3c20e", + "title": "Review Reddit - OpenClaw Production Runbook", + "description": "Production OpenClaw setup guide from Reddit\n\nSource: r/openclaw - u/digitalknk\nURL: https://www.reddit.com/r/openclaw/s/PKq2CUUYMC\n\nTopics:\n- Coordinator vs worker model architecture\n- GPT-5 Nano for background tasks (cost optimization)\n- Memory config that prevents forgetting\n- VPS hardening and git-tracked configs\n\nResources:\n- GitHub Repo: https://github.com/digitalknk/openclaw-runbook\n- Setup Gist: https://gist.github.com/digitalknk/ec360aab27ca47cb4106a183b2c25a98\n- Config Gist: https://gist.github.com/digitalknk/4169b59d01658e20002a093d544eb391\n\nFull summary attached.", + "type": "research", + "status": "done", + "priority": "high", + "project_id": "a1b2c3d4-0001-0000-0000-000000000001", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-22 07:09:45+00", + "updated_at": "2026-02-23 17:32:38.01775+00", + "created_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "updated_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [], + "tags": [ + "openclaw", + "production", + "optimization", + "config", + "attachement" + ], + "attachments": [ + { + "id": "a6cb8aa6-7621-4c58-a620-0f445eb66a22", + "name": "openclaw-runbook-reddit.md", + "size": 2590, + "type": "text/markdown", + "dataUrl": "data:text/markdown;base64,IyBPcGVuQ2xhdyBSdW5ib29rOiBSZWFsLVdvcmxkIFByb2R1Y3Rpb24gU2V0dXAKCioqU291cmNlOioqIFJlZGRpdCByL29wZW5jbGF3IC0gdS9kaWdpdGFsa25rICAKKipEYXRlOioqIEZlYnJ1YXJ5IDIwMjYgIAoqKlVSTDoqKiBodHRwczovL3d3dy5yZWRkaXQuY29tL3Ivb3BlbmNsYXcvcy9QS3EyQ1VVWU1DCgotLS0KCiMjIE92ZXJ2aWV3CgpBIHByYWN0aWNhbCwgYmF0dGxlLXRlc3RlZCBndWlkZSBmb3IgcnVubmluZyBPcGVuQ2xhdyBpbiBwcm9kdWN0aW9uIGFmdGVyICJicmVha2luZyBpdCBhIGJ1bmNoIG9mIHRpbWVzLiIgTm90IGEgaHlwZSBwb3N04oCUanVzdCB3aGF0IGFjdHVhbGx5IHdvcmtzIGZvciBzdGFibGUsIHByZWRpY3RhYmxlLCBjb3N0LWVmZmVjdGl2ZSBvcGVyYXRpb24uCgotLS0KCiMjIEtleSBUb3BpY3MgQ292ZXJlZAoKIyMjIDEuIE1vZGVsIEFyY2hpdGVjdHVyZTogQ29vcmRpbmF0b3IgdnMgV29ya2VyCgoqKkRlZmF1bHQgbW9kZWwgc2hvdWxkIGJlIGEgY29vcmRpbmF0b3IsIG5vdCBhIHdvcmtlcioqCgotIE1haW4gc2Vzc2lvbiBvcmNoZXN0cmF0ZXMKLSBIZWF2eSB3b3JrIGRlbGVnYXRlZCB0byBzdWJhZ2VudHMKLSBQcmV2ZW50cyBjb250ZXh0IGJsb2F0IGFuZCBjcmVkaXQgYnVybgoKIyMjIDIuIENvc3QtT3B0aW1pemVkIEJhY2tncm91bmQgVGFza3MKCioqSGVhcnRiZWF0IGFuZCBiYWNrZ3JvdW5kIHRhc2tzIG9uIEdQVC01IE5hbm8qKgotIEZyYWN0aW9ucyBvZiBhIGNlbnQgcGVyIG9wZXJhdGlvbgotIEVmZmljaWVudCBwb2xsaW5nIHdpdGhvdXQgZXhwZW5zaXZlIG1vZGVsIGNhbGxzCi0gS2VlcHMgbWFpbiBzZXNzaW9uIHJlc3BvbnNpdmUKCiMjIyAzLiBNZW1vcnkgQ29uZmlndXJhdGlvbgoKKipTb2x2ZWQgdGhlICJ3aHkgZGlkIGl0IGZvcmdldCB0aGF0IiBwcm9ibGVtKioKLSBQcm9wZXIgbWVtb3J5IHBlcnNpc3RlbmNlIHNldHVwCi0gRXh0ZXJuYWwgbWVtb3J5IHBhdHRlcm5zCi0gQ29uZmlnIHZhbGlkYXRpb24KCiMjIyA0LiBJbmZyYXN0cnVjdHVyZSAmIE9wZXJhdGlvbnMKCioqVlBTIGhhcmRlbmluZyoqCi0gU2VjdXJpdHkgYmVzdCBwcmFjdGljZXMKLSBDb25maWcgdmFsaWRhdGlvbgotIEdpdC10cmFja2luZyBjb25maWdzIGZvciByb2xsYmFjawoKLS0tCgojIyBSZXNvdXJjZXMKCiMjIyBNYWluIFJ1bmJvb2sKKipHaXRIdWIgUmVwbzoqKiBodHRwczovL2dpdGh1Yi5jb20vZGlnaXRhbGtuay9vcGVuY2xhdy1ydW5ib29rCi0gUmVhbCBjb25maWcgc25pcHBldHMKLSBUcmFkZW9mZnMgZG9jdW1lbnRlZAotIENvbW11bml0eSBjb250cmlidXRpb25zIHdlbGNvbWUKCiMjIyBHaXN0OiBEZXRhaWxlZCBTZXR1cAoqKkxpbms6KiogaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20vZGlnaXRhbGtuay9lYzM2MGFhYjI3Y2E0N2NiNDEwNmExODNiMmMyNWE5OAotIERheS10by1kYXkgb3BlcmF0aW9ucwotIENyZWRpdCBvcHRpbWl6YXRpb24KLSBBdm9pZGluZyBxdW90YS9sb29wIGlzc3VlcwoKIyMjIEdpc3Q6IFNhbml0aXplZCBDb25maWcKKipMaW5rOioqIGh0dHBzOi8vZ2lzdC5naXRodWIuY29tL2RpZ2l0YWxrbmsvNDE2OWI1OWQwMTY1OGUyMDAwMmEwOTNkNTQ0ZWIzOTEKLSBQcm9kdWN0aW9uLXJlYWR5IGNvbmZpZ3VyYXRpb24KLSBTdHJpcHBlZCBvZiBzZW5zaXRpdmUgZGF0YQotIFJlZmVyZW5jZSBpbXBsZW1lbnRhdGlvbgoKLS0tCgojIyBUYXJnZXQgQXVkaWVuY2UKCi0gTmV3IHRvIE9wZW5DbGF3Ci0gRnJ1c3RyYXRlZCB3aXRoIHF1b3RhcyBhbmQgbG9vcHMKLSBXYW50ICJwbGFubmluZyBmb3JldmVyIiBpc3N1ZXMgc29sdmVkCi0gTmVlZCBzdGFibGUsIHByZWRpY3RhYmxlIG9wZXJhdGlvbnMKCi0tLQoKIyMgUGhpbG9zb3BoeQoKPiAiVGhpcyBpcyBub3QgYSBoeXBlIHBvc3QgYW5kIGl0J3Mgbm90IGEgJ2Jlc3Qgc2V0dXAnIGNsYWltLiBJdCdzIGp1c3Qgd2hhdCBlbmRlZCB1cCB3b3JraW5nIGZvciBtZSBvbmNlIHRoZSBub3ZlbHR5IHdvcmUgb2ZmIGFuZCBJIHdhbnRlZCBzb21ldGhpbmcgc3RhYmxlLCBwcmVkaWN0YWJsZSwgYW5kIG5vdCBjb25zdGFudGx5IGJ1cm5pbmcgY3JlZGl0cy4iCgotLS0KCiMjIEFjdGlvbiBJdGVtcwoKLSBbIF0gUmV2aWV3IHJ1bmJvb2sgcmVwbyBmb3IgY29vcmRpbmF0b3IgcGF0dGVybnMKLSBbIF0gSW1wbGVtZW50IEdQVC01IE5hbm8gZm9yIGJhY2tncm91bmQgdGFza3MKLSBbIF0gQXVkaXQgbWVtb3J5IGNvbmZpZyBhZ2FpbnN0IGd1aWRlCi0gWyBdIFNldCB1cCBnaXQtdHJhY2tlZCBjb25maWcgd2l0aCByb2xsYmFjayBjYXBhYmlsaXR5Ci0gWyBdIENvbXBhcmUgY3VycmVudCBzZXR1cCB0byBwcm9kdWN0aW9uIHBhdHRlcm5zCgotLS0KCiMjIFJlbGF0ZWQKCi0gT3BlbkNsYXcgb2ZmaWNpYWwgZG9jcwotIENvbW11bml0eSBEaXNjb3JkL1JlZGRpdCByL29wZW5jbGF3Ci0gQXV0aG9yOiB1L2RpZ2l0YWxrbmsgKGNvbnRyaWJ1dG9yIHRvIE9wZW5DbGF3IGVjb3N5c3RlbSkKCi0tLQoKKkNvbXBpbGVkIGZyb20gUmVkZGl0IHBvc3QqICAKKlN0YXR1czogQWN0aXZlIGNvbW11bml0eSByZXNvdXJjZSwgYWNjZXB0aW5nIGNvbnRyaWJ1dGlvbnMqCg==", + "uploadedAt": "2026-02-22T07:09:51Z" + } + ] + }, + { + "id": "ff2fb52e-03fe-441c-a0f8-95d44300c044", + "title": "Gang Board sorting", + "description": "In all areas where there are task order descending by last updated date so the latest moves to the top", + "type": "task", + "status": "done", + "priority": "medium", + "project_id": "a1b2c3d4-0002-0000-0000-000000000002", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-22 03:50:27.854+00", + "updated_at": "2026-02-22 17:39:57.465775+00", + "created_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "updated_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [], + "tags": [], + "attachments": [] + }, + { + "id": "afe1e8c1-8d86-4736-8438-8c415153a488", + "title": "BUG: Task Details Screen - Comments Not Displaying", + "description": "**Bug Description:**\nComments are being saved to the database but not displaying in the Task Details UI.\n\n**Evidence:**\nTask ID: d9905880-1b03-49e2-8f81-bf0362055571\nDatabase shows comment exists but UI shows empty.\n\n**Expected:** Comments display in task details\n**Actual:** Comments section appears empty\n\n**Fix needed:**\n- Comments render in task details UI\n- Author name and timestamp display\n- Support multiple comments", + "type": "bug", + "status": "open", + "priority": "high", + "project_id": "a1b2c3d4-0002-0000-0000-000000000002", + "sprint_id": "b2c3d4e5-0002-0000-0000-000000000002", + "created_at": "2026-02-23 19:58:41.494012+00", + "updated_at": "2026-02-23 19:58:41.494012+00", + "created_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "updated_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [], + "tags": [ + "gantt-board", + "ui", + "bug", + "comments" + ], + "attachments": [] + }, + { + "id": "ad032eaf-58d5-4783-a5cc-63070774d4e9", + "title": "Custom alerts", + "description": null, + "type": "task", + "status": "review", + "priority": "urgent", + "project_id": "a1b2c3d4-0002-0000-0000-000000000002", + "sprint_id": "b2c3d4e5-0002-0000-0000-000000000002", + "created_at": "2026-02-23 01:15:47.425+00", + "updated_at": "2026-02-23 11:40:20.54047+00", + "created_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "updated_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [], + "tags": [ + "security", + "openclaw" + ], + "attachments": [] + }, + { + "id": "f23dbea9-de4f-4eba-abd3-b52598b7f7ee", + "title": "OpenClaw Tips", + "description": "Find and compile the latest tips and tricks for openclaw and how people are using them. \n\nTake the latest articles and the data and turn this into 1 MD file with attributions and attach it here.", + "type": "task", + "status": "done", + "priority": "high", + "project_id": "a1b2c3d4-0001-0000-0000-000000000001", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-21 23:45:51.141+00", + "updated_at": "2026-02-22 03:04:01.407435+00", + "created_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "updated_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [], + "tags": [ + "openclaw", + "best pratices" + ], + "attachments": [ + { + "id": "ea562623-d035-447e-ae86-99184b5cea15", + "name": "openclaw-tips-2026-02-22.md", + "size": 20553, + "type": "text/markdown", + "dataUrl": "data:text/markdown;base64,IyBPcGVuQ2xhdyBUaXBzLCBUcmlja3MgJiBCZXN0IFByYWN0aWNlcwoKPiAqKkNvbXBpbGVkOioqIEZlYnJ1YXJ5IDIyLCAyMDI2ICAKPiAqKlNvdXJjZToqKiBPZmZpY2lhbCBPcGVuQ2xhdyBEb2N1bWVudGF0aW9uIChkb2NzLm9wZW5jbGF3LmFpKSAmIEdpdEh1YiBSZXBvc2l0b3J5CgotLS0KCiMjIEludHJvZHVjdGlvbgoKT3BlbkNsYXcgaXMgYSBzZWxmLWhvc3RlZCBnYXRld2F5IHRoYXQgY29ubmVjdHMgeW91ciBmYXZvcml0ZSBjaGF0IGFwcHMg4oCUIFdoYXRzQXBwLCBUZWxlZ3JhbSwgRGlzY29yZCwgaU1lc3NhZ2UsIGFuZCBtb3JlIOKAlCB0byBBSSBjb2RpbmcgYWdlbnRzLiBZb3UgcnVuIGEgc2luZ2xlIEdhdGV3YXkgcHJvY2VzcyBvbiB5b3VyIG93biBtYWNoaW5lIChvciBhIHNlcnZlciksIGFuZCBpdCBiZWNvbWVzIHRoZSBicmlkZ2UgYmV0d2VlbiB5b3VyIG1lc3NhZ2luZyBhcHBzIGFuZCBhbiBhbHdheXMtYXZhaWxhYmxlIEFJIGFzc2lzdGFudC4KClRoaXMgZ3VpZGUgY29tcGlsZXMgdGlwcywgdHJpY2tzLCBiZXN0IHByYWN0aWNlcywgYW5kIGNvbW11bml0eSB1c2FnZSBwYXR0ZXJucyBmcm9tIHRoZSBvZmZpY2lhbCBkb2N1bWVudGF0aW9uIHRvIGhlbHAgeW91IGdldCB0aGUgbW9zdCBvdXQgb2YgT3BlbkNsYXcuCgotLS0KCiMjIFRhYmxlIG9mIENvbnRlbnRzCgoxLiBbR2V0dGluZyBTdGFydGVkIFRpcHNdKCNnZXR0aW5nLXN0YXJ0ZWQtdGlwcykKMi4gW0NMSSBVc2FnZSAmIENvbW1hbmRzXSgjY2xpLXVzYWdlLS1jb21tYW5kcykKMy4gW0F1dG9tYXRpb246IENyb24gdnMgSGVhcnRiZWF0XSgjYXV0b21hdGlvbi1jcm9uLXZzLWhlYXJ0YmVhdCkKNC4gW01lbW9yeSBNYW5hZ2VtZW50XSgjbWVtb3J5LW1hbmFnZW1lbnQpCjUuIFtNdWx0aS1BZ2VudCBTZXR1cF0oI211bHRpLWFnZW50LXNldHVwKQo2LiBbU2VjdXJpdHkgQmVzdCBQcmFjdGljZXNdKCNzZWN1cml0eS1iZXN0LXByYWN0aWNlcykKNy4gW0NoYW5uZWwgQ29uZmlndXJhdGlvbl0oI2NoYW5uZWwtY29uZmlndXJhdGlvbikKOC4gW01vZGVsIEZhaWxvdmVyICYgQ29uZmlndXJhdGlvbl0oI21vZGVsLWZhaWxvdmVyLS1jb25maWd1cmF0aW9uKQo5LiBbU2FuZGJveGluZ10oI3NhbmRib3hpbmcpCjEwLiBbUmVtb3RlIEFjY2VzcyAmIERlcGxveW1lbnRdKCNyZW1vdGUtYWNjZXNzLS1kZXBsb3ltZW50KQoxMS4gW1Ryb3VibGVzaG9vdGluZ10oI3Ryb3VibGVzaG9vdGluZykKMTIuIFtBZHZhbmNlZCBDb25maWd1cmF0aW9uXSgjYWR2YW5jZWQtY29uZmlndXJhdGlvbikKCi0tLQoKIyMgR2V0dGluZyBTdGFydGVkIFRpcHMKCiMjIyBRdWljayBJbnN0YWxsIChSZWNvbW1lbmRlZCkKCioqU291cmNlOioqIFtPcGVuQ2xhdyBJbnN0YWxsIEd1aWRlXShodHRwczovL2RvY3Mub3BlbmNsYXcuYWkvaW5zdGFsbCkKCmBgYGJhc2gKIyBtYWNPUyAvIExpbnV4IC8gV1NMMgpjdXJsIC1mc1NMIGh0dHBzOi8vb3BlbmNsYXcuYWkvaW5zdGFsbC5zaCB8IGJhc2gKCiMgV2luZG93cyAoUG93ZXJTaGVsbCkKaXdyIC11c2ViIGh0dHBzOi8vb3BlbmNsYXcuYWkvaW5zdGFsbC5wczEgfCBpZXgKYGBgCgojIyMgRmFzdGVzdCBGaXJzdCBDaGF0CgoqKlNvdXJjZToqKiBbR2V0dGluZyBTdGFydGVkXShodHRwczovL2RvY3Mub3BlbmNsYXcuYWkvc3RhcnQvZ2V0dGluZy1zdGFydGVkKQoKVGhlIGZhc3Rlc3Qgd2F5IHRvIHN0YXJ0IGNoYXR0aW5nIHdpdGhvdXQgc2V0dGluZyB1cCBhbnkgY2hhbm5lbHM6CgpgYGBiYXNoCm9wZW5jbGF3IGRhc2hib2FyZApgYGAKClRoZW4gb3BlbiBgaHR0cDovLzEyNy4wLjAuMToxODc4OS9gIGluIHlvdXIgYnJvd3Nlci4gTm8gY2hhbm5lbCBzZXR1cCByZXF1aXJlZCEKCiMjIyBPbmJvYXJkaW5nIFdpemFyZAoKKipTb3VyY2U6KiogW09uYm9hcmRpbmcgV2l6YXJkXShodHRwczovL2RvY3Mub3BlbmNsYXcuYWkvc3RhcnQvd2l6YXJkKQoKUnVuIHRoZSBndWlkZWQgc2V0dXAgd2l0aCBkYWVtb24gaW5zdGFsbGF0aW9uOgoKYGBgYmFzaApvcGVuY2xhdyBvbmJvYXJkIC0taW5zdGFsbC1kYWVtb24KYGBgCgoqKlBybyBUaXA6KiogU2V0IHVwIGEgQnJhdmUgU2VhcmNoIEFQSSBrZXkgc28gdGhlIGFnZW50IGNhbiB1c2UgYHdlYl9zZWFyY2hgOgpgYGBiYXNoCm9wZW5jbGF3IGNvbmZpZ3VyZSAtLXNlY3Rpb24gd2ViCmBgYAoKIyMjIFN5c3RlbSBSZXF1aXJlbWVudHMKCi0gKipOb2RlIDIyKyoqIChpbnN0YWxsZXIgd2lsbCBpbnN0YWxsIGlmIG1pc3NpbmcpCi0gbWFjT1MsIExpbnV4LCBvciBXaW5kb3dzIChXU0wyIHN0cm9uZ2x5IHJlY29tbWVuZGVkIGZvciBXaW5kb3dzKQoKLS0tCgojIyBDTEkgVXNhZ2UgJiBDb21tYW5kcwoKIyMjIEVzc2VudGlhbCBDTEkgQ29tbWFuZHMKCioqU291cmNlOioqIFtDTEkgUmVmZXJlbmNlXShodHRwczovL2RvY3Mub3BlbmNsYXcuYWkvY2xpL2luZGV4KQoKfCBDb21tYW5kIHwgUHVycG9zZSB8CnwtLS0tLS0tLS18LS0tLS0tLS0tfAp8IGBvcGVuY2xhdyBzdGF0dXNgIHwgQ2hlY2sgb3ZlcmFsbCBzdGF0dXMgfAp8IGBvcGVuY2xhdyBzdGF0dXMgLS1hbGxgIHwgRnVsbCBkaWFnbm9zdGljIHJlcG9ydCB8CnwgYG9wZW5jbGF3IGdhdGV3YXkgc3RhdHVzYCB8IENoZWNrIGdhdGV3YXkgcnVudGltZSB8CnwgYG9wZW5jbGF3IGdhdGV3YXkgcHJvYmVgIHwgVGVzdCBnYXRld2F5IGNvbm5lY3Rpdml0eSB8CnwgYG9wZW5jbGF3IGRvY3RvcmAgfCBSdW4gZGlhZ25vc3RpY3MgYW5kIGNvbmZpZyBjaGVja3MgfAp8IGBvcGVuY2xhdyBjaGFubmVscyBzdGF0dXMgLS1wcm9iZWAgfCBDaGVjayBjaGFubmVsIGNvbm5lY3Rpb25zIHwKfCBgb3BlbmNsYXcgbG9ncyAtLWZvbGxvd2AgfCBMaXZlIGxvZyBzdHJlYW1pbmcgfAoKIyMjIEdhdGV3YXkgTWFuYWdlbWVudAoKYGBgYmFzaAojIFN0YXJ0IGdhdGV3YXkgaW4gZm9yZWdyb3VuZCAoZm9yIHRlc3RpbmcpCm9wZW5jbGF3IGdhdGV3YXkgLS1wb3J0IDE4Nzg5CgojIFN0YXJ0L3N0b3AvcmVzdGFydCBzZXJ2aWNlCm9wZW5jbGF3IGdhdGV3YXkgc3RhcnQKb3BlbmNsYXcgZ2F0ZXdheSBzdG9wCm9wZW5jbGF3IGdhdGV3YXkgcmVzdGFydAoKIyBDaGVjayBoZWFsdGgKb3BlbmNsYXcgaGVhbHRoCmBgYAoKIyMjIENvbmZpZ3VyYXRpb24gQ29tbWFuZHMKCmBgYGJhc2gKIyBTZXQgY29uZmlnIHZhbHVlcwpvcGVuY2xhdyBjb25maWcgc2V0IGNoYW5uZWxzLnRlbGVncmFtLmVuYWJsZWQgdHJ1ZSAtLWpzb24Kb3BlbmNsYXcgY29uZmlnIHNldCBjaGFubmVscy5kaXNjb3JkLnRva2VuICciWU9VUl9UT0tFTiInIC0tanNvbgoKIyBBcHBseSBhbmQgcmVzdGFydApvcGVuY2xhdyBjb25maWcgYXBwbHkKYGBgCgojIyMgRW52aXJvbm1lbnQgVmFyaWFibGVzCgoqKlNvdXJjZToqKiBbR2V0dGluZyBTdGFydGVkXShodHRwczovL2RvY3Mub3BlbmNsYXcuYWkvc3RhcnQvZ2V0dGluZy1zdGFydGVkKQoKfCBWYXJpYWJsZSB8IFB1cnBvc2UgfAp8LS0tLS0tLS0tLXwtLS0tLS0tLS18CnwgYE9QRU5DTEFXX0hPTUVgIHwgSG9tZSBkaXJlY3RvcnkgZm9yIGludGVybmFsIHBhdGggcmVzb2x1dGlvbiB8CnwgYE9QRU5DTEFXX1NUQVRFX0RJUmAgfCBPdmVycmlkZSBzdGF0ZSBkaXJlY3RvcnkgfAp8IGBPUEVOQ0xBV19DT05GSUdfUEFUSGAgfCBPdmVycmlkZSBjb25maWcgZmlsZSBwYXRoIHwKCi0tLQoKIyMgQXV0b21hdGlvbjogQ3JvbiB2cyBIZWFydGJlYXQKCiMjIyBXaGVuIHRvIFVzZSBFYWNoCgoqKlNvdXJjZToqKiBbQ3JvbiB2cyBIZWFydGJlYXQgR3VpZGVdKGh0dHBzOi8vZG9jcy5vcGVuY2xhdy5haS9hdXRvbWF0aW9uL2Nyb24tdnMtaGVhcnRiZWF0KQoKfCBVc2UgQ2FzZSB8IFJlY29tbWVuZGVkIHwgV2h5IHwKfC0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLXwtLS0tLXwKfCBDaGVjayBpbmJveCBldmVyeSAzMCBtaW4gfCAqKkhlYXJ0YmVhdCoqIHwgQmF0Y2hlcyB3aXRoIG90aGVyIGNoZWNrcywgY29udGV4dC1hd2FyZSB8CnwgU2VuZCBkYWlseSByZXBvcnQgYXQgOWFtIHNoYXJwIHwgKipDcm9uIChpc29sYXRlZCkqKiB8IEV4YWN0IHRpbWluZyBuZWVkZWQgfAp8IE1vbml0b3IgY2FsZW5kYXIgZm9yIHVwY29taW5nIGV2ZW50cyB8ICoqSGVhcnRiZWF0KiogfCBOYXR1cmFsIGZpdCBmb3IgcGVyaW9kaWMgYXdhcmVuZXNzIHwKfCBSdW4gd2Vla2x5IGRlZXAgYW5hbHlzaXMgfCAqKkNyb24gKGlzb2xhdGVkKSoqIHwgU3RhbmRhbG9uZSB0YXNrLCBjYW4gdXNlIGRpZmZlcmVudCBtb2RlbCB8CnwgUmVtaW5kIG1lIGluIDIwIG1pbnV0ZXMgfCAqKkNyb24gKG1haW4sIGAtLWF0YCkqKiB8IE9uZS1zaG90IHdpdGggcHJlY2lzZSB0aW1pbmcgfAp8IEJhY2tncm91bmQgcHJvamVjdCBoZWFsdGggY2hlY2sgfCAqKkhlYXJ0YmVhdCoqIHwgUGlnZ3liYWNrcyBvbiBleGlzdGluZyBjeWNsZSB8CgojIyMgSGVhcnRiZWF0IENvbmZpZ3VyYXRpb24KCioqU291cmNlOioqIFtIZWFydGJlYXQgR3VpZGVdKGh0dHBzOi8vZG9jcy5vcGVuY2xhdy5haS9nYXRld2F5L2hlYXJ0YmVhdCkKCmBgYGpzb241CnsKICBhZ2VudHM6IHsKICAgIGRlZmF1bHRzOiB7CiAgICAgIGhlYXJ0YmVhdDogewogICAgICAgIGV2ZXJ5OiAiMzBtIiwgICAgICAgICAgIC8vIEludGVydmFsIChkZWZhdWx0OiAzMG0gb3IgMWggZm9yIEFudGhyb3BpYyBPQXV0aCkKICAgICAgICB0YXJnZXQ6ICJsYXN0IiwgICAgICAgICAvLyBXaGVyZSB0byBkZWxpdmVyIGFsZXJ0cwogICAgICAgIGluY2x1ZGVSZWFzb25pbmc6IGZhbHNlLC8vIE9wdGlvbmFsOiBzZW5kIHNlcGFyYXRlIFJlYXNvbmluZyBtZXNzYWdlCiAgICAgICAgYWN0aXZlSG91cnM6IHsgICAgICAgICAgLy8gT3B0aW9uYWw6IHJlc3RyaWN0IHRvIGFjdGl2ZSBob3VycwogICAgICAgICAgc3RhcnQ6ICIwODowMCIsCiAgICAgICAgICBlbmQ6ICIyMjowMCIKICAgICAgICB9LAogICAgICB9LAogICAgfSwKICB9LAp9CmBgYAoKKipEZWZhdWx0IGhlYXJ0YmVhdCBwcm9tcHQ6KioKYGBgClJlYWQgSEVBUlRCRUFULm1kIGlmIGl0IGV4aXN0cyAod29ya3NwYWNlIGNvbnRleHQpLiBGb2xsb3cgaXQgc3RyaWN0bHkuIApEbyBub3QgaW5mZXIgb3IgcmVwZWF0IG9sZCB0YXNrcyBmcm9tIHByaW9yIGNoYXRzLiBJZiBub3RoaW5nIG5lZWRzIAphdHRlbnRpb24sIHJlcGx5IEhFQVJUQkVBVF9PSy4KYGBgCgojIyMgQ3JlYXRpbmcgSEVBUlRCRUFULm1kCgoqKlNvdXJjZToqKiBbQWdlbnQgR3VpZGVdKGh0dHBzOi8vZG9jcy5vcGVuY2xhdy5haS9hZ2VudHMpCgpDcmVhdGUgYSBgSEVBUlRCRUFULm1kYCBmaWxlIGluIHlvdXIgd29ya3NwYWNlIGZvciBwZXJpb2RpYyBjaGVja3M6CgpgYGBtYXJrZG93bgojIEhlYXJ0YmVhdCBDaGVja2xpc3QKCi0gQ2hlY2sgZW1haWwgZm9yIHVyZ2VudCBtZXNzYWdlcwotIFJldmlldyBjYWxlbmRhciBmb3IgZXZlbnRzIGluIG5leHQgMiBob3VycwotIElmIGEgYmFja2dyb3VuZCB0YXNrIGZpbmlzaGVkLCBzdW1tYXJpemUgcmVzdWx0cwotIElmIGlkbGUgZm9yIDgrIGhvdXJzLCBzZW5kIGEgYnJpZWYgY2hlY2staW4KYGBgCgoqKlRpcDoqKiBUaGUgYWdlbnQgcmVhZHMgdGhpcyBvbiBlYWNoIGhlYXJ0YmVhdCBhbmQgaGFuZGxlcyBhbGwgaXRlbXMgaW4gb25lIHR1cm4uCgojIyMgQ3JvbiBKb2IgRXhhbXBsZXMKCioqU291cmNlOioqIFtDcm9uIEpvYnMgR3VpZGVdKGh0dHBzOi8vZG9jcy5vcGVuY2xhdy5haS9hdXRvbWF0aW9uL2Nyb24tam9icykKCmBgYGJhc2gKIyBPbmUtc2hvdCByZW1pbmRlcgpvcGVuY2xhdyBjcm9uIGFkZCBcCiAgLS1uYW1lICJSZW1pbmRlciIgXAogIC0tYXQgIjIwMjYtMDItMDFUMTY6MDA6MDBaIiBcCiAgLS1zZXNzaW9uIG1haW4gXAogIC0tc3lzdGVtLWV2ZW50ICJSZW1pbmRlcjogY2hlY2sgdGhlIGNyb24gZG9jcyBkcmFmdCIgXAogIC0td2FrZSBub3cgXAogIC0tZGVsZXRlLWFmdGVyLXJ1bgoKIyBSZWN1cnJpbmcgaXNvbGF0ZWQgam9iIHdpdGggZGVsaXZlcnkKb3BlbmNsYXcgY3JvbiBhZGQgXAogIC0tbmFtZSAiTW9ybmluZyBicmllZiIgXAogIC0tY3JvbiAiMCA3ICogKiAqIiBcCiAgLS10eiAiQW1lcmljYS9Mb3NfQW5nZWxlcyIgXAogIC0tc2Vzc2lvbiBpc29sYXRlZCBcCiAgLS1tZXNzYWdlICJTdW1tYXJpemUgb3Zlcm5pZ2h0IHVwZGF0ZXMuIiBcCiAgLS1hbm5vdW5jZSBcCiAgLS1jaGFubmVsIHNsYWNrIFwKICAtLXRvICJjaGFubmVsOkMxMjM0NTY3ODkwIgpgYGAKCioqQ3JvbiBzdG9yYWdlIGxvY2F0aW9uOioqIGB+Ly5vcGVuY2xhdy9jcm9uL2pvYnMuanNvbmAKCi0tLQoKIyMgTWVtb3J5IE1hbmFnZW1lbnQKCiMjIyBNZW1vcnkgRmlsZXMgU3RydWN0dXJlCgoqKlNvdXJjZToqKiBbTWVtb3J5IENvbmNlcHRzXShodHRwczovL2RvY3Mub3BlbmNsYXcuYWkvY29uY2VwdHMvbWVtb3J5KQoKT3BlbkNsYXcgdXNlcyBwbGFpbiBNYXJrZG93biBmaWxlcyBmb3IgbWVtb3J5OgoKfCBGaWxlIHwgUHVycG9zZSB8CnwtLS0tLS18LS0tLS0tLS0tfAp8IGBtZW1vcnkvWVlZWS1NTS1ERC5tZGAgfCBEYWlseSBsb2cgKGFwcGVuZC1vbmx5KSwgcmVhZHMgdG9kYXkgKyB5ZXN0ZXJkYXkgYXQgc2Vzc2lvbiBzdGFydCB8CnwgYE1FTU9SWS5tZGAgfCBDdXJhdGVkIGxvbmctdGVybSBtZW1vcnkgKG9ubHkgbG9hZCBpbiBtYWluLCBwcml2YXRlIHNlc3Npb24pIHwKCioqV29ya3NwYWNlIGxvY2F0aW9uOioqIGB+Ly5vcGVuY2xhdy93b3Jrc3BhY2VgIChvciBjb25maWd1cmVkIHBhdGgpCgojIyMgV2hlbiB0byBXcml0ZSBNZW1vcnkKCioqU291cmNlOioqIFtNZW1vcnkgR3VpZGVdKGh0dHBzOi8vZG9jcy5vcGVuY2xhdy5haS9jb25jZXB0cy9tZW1vcnkpCgotICoqRGVjaXNpb25zLCBwcmVmZXJlbmNlcywgZHVyYWJsZSBmYWN0cyoqIOKGkiBgTUVNT1JZLm1kYAotICoqRGF5LXRvLWRheSBub3RlcywgcnVubmluZyBjb250ZXh0Kiog4oaSIGBtZW1vcnkvWVlZWS1NTS1ERC5tZGAKLSBJZiBzb21lb25lIHNheXMgInJlbWVtYmVyIHRoaXMsIiAqKndyaXRlIGl0IGRvd24qKiAoZG9uJ3Qga2VlcCBpdCBpbiBSQU0pCi0gSWYgeW91IHdhbnQgc29tZXRoaW5nIHRvIHN0aWNrLCAqKmFzayB0aGUgYm90IHRvIHdyaXRlIGl0KiogaW50byBtZW1vcnkKCiMjIyBBdXRvbWF0aWMgTWVtb3J5IEZsdXNoCgoqKlNvdXJjZToqKiBbTWVtb3J5IEd1aWRlXShodHRwczovL2RvY3Mub3BlbmNsYXcuYWkvY29uY2VwdHMvbWVtb3J5KQoKV2hlbiBhIHNlc3Npb24gbmVhcnMgYXV0by1jb21wYWN0aW9uLCBPcGVuQ2xhdyB0cmlnZ2VycyBhIHNpbGVudCB0dXJuIHRvIHJlbWluZCB0aGUgbW9kZWwgdG8gd3JpdGUgZHVyYWJsZSBub3RlcyBiZWZvcmUgY29udGV4dCBpcyBsb3N0LgoKYGBganNvbjUKewogIGFnZW50czogewogICAgZGVmYXVsdHM6IHsKICAgICAgY29tcGFjdGlvbjogewogICAgICAgIG1lbW9yeUZsdXNoOiB7CiAgICAgICAgICBlbmFibGVkOiB0cnVlLAogICAgICAgICAgc29mdFRocmVzaG9sZFRva2VuczogNDAwMCwKICAgICAgICAgIHN5c3RlbVByb21wdDogIlNlc3Npb24gbmVhcmluZyBjb21wYWN0aW9uLiBTdG9yZSBkdXJhYmxlIG1lbW9yaWVzIG5vdy4iLAogICAgICAgICAgcHJvbXB0OiAiV3JpdGUgbGFzdGluZyBub3RlcyB0byBtZW1vcnkvWVlZWS1NTS1ERC5tZDsgcmVwbHkgTk9fUkVQTFkgaWYgbm90aGluZyB0byBzdG9yZS4iLAogICAgICAgIH0sCiAgICAgIH0sCiAgICB9LAogIH0sCn0KYGBgCgojIyMgVmVjdG9yIE1lbW9yeSBTZWFyY2gKCioqU291cmNlOioqIFtNZW1vcnkgR3VpZGVdKGh0dHBzOi8vZG9jcy5vcGVuY2xhdy5haS9jb25jZXB0cy9tZW1vcnkpCgpPcGVuQ2xhdyBjYW4gYnVpbGQgYSB2ZWN0b3IgaW5kZXggb3ZlciBtZW1vcnkgZmlsZXMgZm9yIHNlbWFudGljIHNlYXJjaDoKCi0gRW5hYmxlZCBieSBkZWZhdWx0Ci0gV2F0Y2hlcyBtZW1vcnkgZmlsZXMgZm9yIGNoYW5nZXMgKGRlYm91bmNlZCkKLSBBdXRvLXNlbGVjdHMgcHJvdmlkZXI6IGBsb2NhbGAg4oaSIGBvcGVuYWlgIOKGkiBgZ2VtaW5pYCDihpIgYHZveWFnZWAKCi0tLQoKIyMgTXVsdGktQWdlbnQgU2V0dXAKCiMjIyBXaGF0IGlzIGFuIEFnZW50PwoKKipTb3VyY2U6KiogW011bHRpLUFnZW50IFJvdXRpbmddKGh0dHBzOi8vZG9jcy5vcGVuY2xhdy5haS9jb25jZXB0cy9tdWx0aS1hZ2VudCkKCkFuIGFnZW50IGlzIGEgZnVsbHkgc2NvcGVkIGJyYWluIHdpdGggaXRzIG93bjoKLSAqKldvcmtzcGFjZSoqIChmaWxlcywgQUdFTlRTLm1kL1NPVUwubWQvVVNFUi5tZCkKLSAqKlN0YXRlIGRpcmVjdG9yeSoqIChgYWdlbnREaXJgKSBmb3IgYXV0aCBwcm9maWxlcyBhbmQgY29uZmlnCi0gKipTZXNzaW9uIHN0b3JlKiogdW5kZXIgYH4vLm9wZW5jbGF3L2FnZW50cy88YWdlbnRJZD4vc2Vzc2lvbnNgCgojIyMgQ3JlYXRpbmcgTXVsdGlwbGUgQWdlbnRzCgpgYGBiYXNoCiMgQWRkIG5ldyBhZ2VudCB3aXRoIHdpemFyZApvcGVuY2xhdyBhZ2VudHMgYWRkIHdvcmsKb3BlbmNsYXcgYWdlbnRzIGFkZCBjb2RpbmcKb3BlbmNsYXcgYWdlbnRzIGFkZCBzb2NpYWwKCiMgTGlzdCBhZ2VudHMgd2l0aCBiaW5kaW5ncwpvcGVuY2xhdyBhZ2VudHMgbGlzdCAtLWJpbmRpbmdzCmBgYAoKIyMjIEtleSBQYXRocwoKfCBQYXRoIHwgRGVzY3JpcHRpb24gfAp8LS0tLS0tfC0tLS0tLS0tLS0tLS18CnwgYH4vLm9wZW5jbGF3L29wZW5jbGF3Lmpzb25gIHwgTWFpbiBjb25maWcgfAp8IGB+Ly5vcGVuY2xhd2AgfCBTdGF0ZSBkaXJlY3RvcnkgfAp8IGB+Ly5vcGVuY2xhdy93b3Jrc3BhY2VgIHwgRGVmYXVsdCB3b3Jrc3BhY2UgfAp8IGB+Ly5vcGVuY2xhdy9hZ2VudHMvPGFnZW50SWQ+L2FnZW50YCB8IEFnZW50LXNwZWNpZmljIHN0YXRlIHwKfCBgfi8ub3BlbmNsYXcvYWdlbnRzLzxhZ2VudElkPi9zZXNzaW9uc2AgfCBTZXNzaW9uIHN0b3JlIHwKCiMjIyBBdXRoIFByb2ZpbGVzIFBlciBBZ2VudAoKKipTb3VyY2U6KiogW011bHRpLUFnZW50IEd1aWRlXShodHRwczovL2RvY3Mub3BlbmNsYXcuYWkvY29uY2VwdHMvbXVsdGktYWdlbnQpCgpFYWNoIGFnZW50IGhhcyBpdHMgb3duIGF1dGggcHJvZmlsZXM6CgpgYGAKfi8ub3BlbmNsYXcvYWdlbnRzLzxhZ2VudElkPi9hZ2VudC9hdXRoLXByb2ZpbGVzLmpzb24KYGBgCgpNYWluIGFnZW50IGNyZWRlbnRpYWxzIGFyZSAqKm5vdCoqIHNoYXJlZCBhdXRvbWF0aWNhbGx5LiBDb3B5IGBhdXRoLXByb2ZpbGVzLmpzb25gIGlmIHlvdSB3YW50IHRvIHNoYXJlIGNyZWRzIGJldHdlZW4gYWdlbnRzLgoKLS0tCgojIyBTZWN1cml0eSBCZXN0IFByYWN0aWNlcwoKIyMjIFNlY3VyZSBETSBNb2RlIChNdWx0aS1Vc2VyIFNldHVwcykKCioqU291cmNlOioqIFtTZXNzaW9uIE1hbmFnZW1lbnRdKGh0dHBzOi8vZG9jcy5vcGVuY2xhdy5haS9jb25jZXB0cy9zZXNzaW9uKQoK4pqg77iPICoqQ3JpdGljYWw6KiogSWYgeW91ciBhZ2VudCBjYW4gcmVjZWl2ZSBETXMgZnJvbSBtdWx0aXBsZSBwZW9wbGUsIGVuYWJsZSBzZWN1cmUgRE0gbW9kZToKCmBgYGpzb241CnsKICBzZXNzaW9uOiB7CiAgICBkbVNjb3BlOiAicGVyLWNoYW5uZWwtcGVlciIsICAvLyBJc29sYXRlIERNIGNvbnRleHQgcGVyIGNoYW5uZWwgKyBzZW5kZXIKICB9LAp9CmBgYAoKKipPcHRpb25zOioqCi0gYG1haW5gIChkZWZhdWx0KTogQWxsIERNcyBzaGFyZSBtYWluIHNlc3Npb24gKGZpbmUgZm9yIHNpbmdsZS11c2VyKQotIGBwZXItcGVlcmA6IElzb2xhdGUgYnkgc2VuZGVyIElEIGFjcm9zcyBjaGFubmVscwotIGBwZXItY2hhbm5lbC1wZWVyYDogSXNvbGF0ZSBieSBjaGFubmVsICsgc2VuZGVyIChyZWNvbW1lbmRlZCBmb3IgbXVsdGktdXNlcikKLSBgcGVyLWFjY291bnQtY2hhbm5lbC1wZWVyYDogSXNvbGF0ZSBieSBhY2NvdW50ICsgY2hhbm5lbCArIHNlbmRlcgoKIyMjIFNlY3VyaXR5IEF1ZGl0CgpgYGBiYXNoCm9wZW5jbGF3IHNlY3VyaXR5IGF1ZGl0CmBgYAoKIyMjIERldmljZSBQYWlyaW5nCgoqKlNvdXJjZToqKiBbQ29udHJvbCBVSV0oaHR0cHM6Ly9kb2NzLm9wZW5jbGF3LmFpL3dlYi9jb250cm9sLXVpKQoKUmVtb3RlIGNvbm5lY3Rpb25zIHJlcXVpcmUgZXhwbGljaXQgZGV2aWNlIGFwcHJvdmFsOgoKYGBgYmFzaAojIExpc3QgcGVuZGluZyByZXF1ZXN0cwpvcGVuY2xhdyBkZXZpY2VzIGxpc3QKCiMgQXBwcm92ZSBkZXZpY2UKb3BlbmNsYXcgZGV2aWNlcyBhcHByb3ZlIDxyZXF1ZXN0SWQ+CgojIFJldm9rZSBkZXZpY2UKb3BlbmNsYXcgZGV2aWNlcyByZXZva2UgLS1kZXZpY2UgPGlkPiAtLXJvbGUgPHJvbGU+CmBgYAoKIyMjIFRva2VuIFNlY3VyaXR5CgotIExvY2FsIGNvbm5lY3Rpb25zIChgMTI3LjAuMC4xYCkgYXJlIGF1dG8tYXBwcm92ZWQKLSBSZW1vdGUgY29ubmVjdGlvbnMgKExBTiwgVGFpbG5ldCkgcmVxdWlyZSBleHBsaWNpdCBhcHByb3ZhbAotIEVhY2ggYnJvd3NlciBwcm9maWxlIGdlbmVyYXRlcyBhIHVuaXF1ZSBkZXZpY2UgSUQKCi0tLQoKIyMgQ2hhbm5lbCBDb25maWd1cmF0aW9uCgojIyMgVGVsZWdyYW0gU2V0dXAKCioqU291cmNlOioqIFtUZWxlZ3JhbSBDaGFubmVsIEd1aWRlXShodHRwczovL2RvY3Mub3BlbmNsYXcuYWkvY2hhbm5lbHMvdGVsZWdyYW0pCgpgYGBqc29uNQp7CiAgY2hhbm5lbHM6IHsKICAgIHRlbGVncmFtOiB7CiAgICAgIGVuYWJsZWQ6IHRydWUsCiAgICAgIGJvdFRva2VuOiAiMTIzOmFiYyIsCiAgICAgIGRtUG9saWN5OiAicGFpcmluZyIsICAgICAgLy8gcGFpcmluZyB8IGFsbG93bGlzdCB8IG9wZW4gfCBkaXNhYmxlZAogICAgICBncm91cHM6IHsgIioiOiB7IHJlcXVpcmVNZW50aW9uOiB0cnVlIH0gfSwKICAgIH0sCiAgfSwKfQpgYGAKCioqRmluZGluZyB5b3VyIFRlbGVncmFtIHVzZXIgSUQ6KioKMS4gRE0geW91ciBib3QKMi4gUnVuIGBvcGVuY2xhdyBsb2dzIC0tZm9sbG93YAozLiBSZWFkIGBmcm9tLmlkYCBpbiBsb2dzCgojIyMgRGlzY29yZCBTZXR1cAoKKipTb3VyY2U6KiogW0Rpc2NvcmQgQ2hhbm5lbCBHdWlkZV0oaHR0cHM6Ly9kb2NzLm9wZW5jbGF3LmFpL2NoYW5uZWxzL2Rpc2NvcmQpCgoqKlJlcXVpcmVkIEJvdCBQZXJtaXNzaW9uczoqKgotIFZpZXcgQ2hhbm5lbHMKLSBTZW5kIE1lc3NhZ2VzCi0gUmVhZCBNZXNzYWdlIEhpc3RvcnkKLSBFbWJlZCBMaW5rcwotIEF0dGFjaCBGaWxlcwotIEFkZCBSZWFjdGlvbnMgKG9wdGlvbmFsKQoKKipSZXF1aXJlZCBHYXRld2F5IEludGVudHM6KioKLSBNZXNzYWdlIENvbnRlbnQgSW50ZW50IChyZXF1aXJlZCkKLSBTZXJ2ZXIgTWVtYmVycyBJbnRlbnQgKHJlY29tbWVuZGVkKQotIFByZXNlbmNlIEludGVudCAob3B0aW9uYWwpCgpgYGBqc29uNQp7CiAgY2hhbm5lbHM6IHsKICAgIGRpc2NvcmQ6IHsKICAgICAgZW5hYmxlZDogdHJ1ZSwKICAgICAgdG9rZW46ICJZT1VSX0JPVF9UT0tFTiIsCiAgICAgIGRtUG9saWN5OiAicGFpcmluZyIsCiAgICB9LAogIH0sCn0KYGBgCgojIyMgV2hhdHNBcHAsIFNpZ25hbCwgaU1lc3NhZ2UKCioqU291cmNlOioqIFtDaGFubmVsIEd1aWRlc10oaHR0cHM6Ly9kb2NzLm9wZW5jbGF3LmFpL2NoYW5uZWxzLykKCkNoZWNrIHBhaXJpbmcgc3RhdHVzOgpgYGBiYXNoCm9wZW5jbGF3IHBhaXJpbmcgbGlzdCA8Y2hhbm5lbD4Kb3BlbmNsYXcgcGFpcmluZyBhcHByb3ZlIDxjaGFubmVsPiA8Q09ERT4KYGBgCgotLS0KCiMjIE1vZGVsIEZhaWxvdmVyICYgQ29uZmlndXJhdGlvbgoKIyMjIEF1dGggUHJvZmlsZSBSb3RhdGlvbgoKKipTb3VyY2U6KiogW01vZGVsIEZhaWxvdmVyXShodHRwczovL2RvY3Mub3BlbmNsYXcuYWkvY29uY2VwdHMvbW9kZWwtZmFpbG92ZXIpCgpPcGVuQ2xhdyBoYW5kbGVzIGZhaWx1cmVzIGluIHR3byBzdGFnZXM6CjEuICoqQXV0aCBwcm9maWxlIHJvdGF0aW9uKiogd2l0aGluIGN1cnJlbnQgcHJvdmlkZXIKMi4gKipNb2RlbCBmYWxsYmFjayoqIHRvIG5leHQgbW9kZWwgaW4gYGFnZW50cy5kZWZhdWx0cy5tb2RlbC5mYWxsYmFja3NgCgojIyMgQXV0aCBTdG9yYWdlCgpTZWNyZXRzIGxpdmUgaW46CmBgYAp+Ly5vcGVuY2xhdy9hZ2VudHMvPGFnZW50SWQ+L2FnZW50L2F1dGgtcHJvZmlsZXMuanNvbgpgYGAKCioqUHJvZmlsZSBJRCBmb3JtYXQ6KioKLSBEZWZhdWx0OiBgcHJvdmlkZXI6ZGVmYXVsdGAKLSBPQXV0aCB3aXRoIGVtYWlsOiBgcHJvdmlkZXI6PGVtYWlsPmAKCiMjIyBTZXNzaW9uIFN0aWNraW5lc3MKCk9wZW5DbGF3ICoqcGlucyB0aGUgY2hvc2VuIGF1dGggcHJvZmlsZSBwZXIgc2Vzc2lvbioqIHRvIGtlZXAgcHJvdmlkZXIgY2FjaGVzIHdhcm0uIFRoZSBwaW5uZWQgcHJvZmlsZSBpcyByZXVzZWQgdW50aWw6Ci0gU2Vzc2lvbiBpcyByZXNldCAoYC9uZXdgIC8gYC9yZXNldGApCi0gQ29tcGFjdGlvbiBjb21wbGV0ZXMKLSBQcm9maWxlIGlzIGluIGNvb2xkb3duL2Rpc2FibGVkCgojIyMgQ29vbGRvd25zCgpXaGVuIGEgcHJvZmlsZSBmYWlscywgT3BlbkNsYXcgbWFya3MgaXQgaW4gY29vbGRvd24gd2l0aCBleHBvbmVudGlhbCBiYWNrb2ZmOgotIDEgbWludXRlIOKGkiA1IG1pbnV0ZXMg4oaSIDI1IG1pbnV0ZXMg4oaSIDEgaG91ciAoY2FwKQoKIyMjIE1vZGVsIENvbmZpZ3VyYXRpb24gRXhhbXBsZQoKKipTb3VyY2U6KiogW0NvbmZpZ3VyYXRpb24gRXhhbXBsZXNdKGh0dHBzOi8vZG9jcy5vcGVuY2xhdy5haS9nYXRld2F5L2NvbmZpZ3VyYXRpb24tZXhhbXBsZXMpCgpgYGBqc29uNQp7CiAgYWdlbnQ6IHsKICAgIG1vZGVsOiB7IAogICAgICBwcmltYXJ5OiAiYW50aHJvcGljL2NsYXVkZS1zb25uZXQtNC01IiwKICAgICAgZmFsbGJhY2tzOiBbIm9wZW5haS9ncHQtNS4yLW1pbmkiLCAiZ29vZ2xlL2dlbWluaS0zLWZsYXNoIl0KICAgIH0sCiAgfSwKICBhdXRoOiB7CiAgICBwcm9maWxlczogewogICAgICAiYW50aHJvcGljOm1lQGV4YW1wbGUuY29tIjogewogICAgICAgIHByb3ZpZGVyOiAiYW50aHJvcGljIiwKICAgICAgICBtb2RlOiAib2F1dGgiLAogICAgICAgIGVtYWlsOiAibWVAZXhhbXBsZS5jb20iLAogICAgICB9LAogICAgfSwKICAgIG9yZGVyOiB7CiAgICAgIGFudGhyb3BpYzogWyJhbnRocm9waWM6bWVAZXhhbXBsZS5jb20iXSwKICAgIH0sCiAgfSwKfQpgYGAKCi0tLQoKIyMgU2FuZGJveGluZwoKIyMjIFNhbmRib3hpbmcgTW9kZXMKCioqU291cmNlOioqIFtTYW5kYm94aW5nIEd1aWRlXShodHRwczovL2RvY3Mub3BlbmNsYXcuYWkvZ2F0ZXdheS9zYW5kYm94aW5nKQoKYGBganNvbjUKewogIGFnZW50czogewogICAgZGVmYXVsdHM6IHsKICAgICAgc2FuZGJveDogewogICAgICAgIG1vZGU6ICJub24tbWFpbiIsICAgICAgLy8gb2ZmIHwgbm9uLW1haW4gfCBhbGwKICAgICAgICBzY29wZTogInNlc3Npb24iLCAgICAgIC8vIHNlc3Npb24gfCBhZ2VudCB8IHNoYXJlZAogICAgICAgIHdvcmtzcGFjZUFjY2VzczogIm5vbmUiLCAvLyBub25lIHwgcm8gfCBydwogICAgICB9LAogICAgfSwKICB9LAp9CmBgYAoKKipNb2RlczoqKgotIGBvZmZgOiBObyBzYW5kYm94aW5nCi0gYG5vbi1tYWluYDogU2FuZGJveCBvbmx5IG5vbi1tYWluIHNlc3Npb25zIChkZWZhdWx0IHJlY29tbWVuZGF0aW9uKQotIGBhbGxgOiBFdmVyeSBzZXNzaW9uIHJ1bnMgaW4gc2FuZGJveAoKKipTY29wZXM6KioKLSBgc2Vzc2lvbmA6IE9uZSBjb250YWluZXIgcGVyIHNlc3Npb24KLSBgYWdlbnRgOiBPbmUgY29udGFpbmVyIHBlciBhZ2VudAotIGBzaGFyZWRgOiBPbmUgY29udGFpbmVyIHNoYXJlZCBieSBhbGwgc2FuZGJveGVkIHNlc3Npb25zCgoqKldvcmtzcGFjZSBBY2Nlc3M6KioKLSBgbm9uZWA6IFNhbmRib3ggd29ya3NwYWNlIHVuZGVyIGB+Ly5vcGVuY2xhdy9zYW5kYm94ZXNgCi0gYHJvYDogTW91bnQgYWdlbnQgd29ya3NwYWNlIHJlYWQtb25seSBhdCBgL2FnZW50YAotIGByd2A6IE1vdW50IGFnZW50IHdvcmtzcGFjZSByZWFkL3dyaXRlIGF0IGAvd29ya3NwYWNlYAoKIyMjIFdoYXQgR2V0cyBTYW5kYm94ZWQKCi0gVG9vbCBleGVjdXRpb24gKGBleGVjYCwgYHJlYWRgLCBgd3JpdGVgLCBgZWRpdGAsIGBwcm9jZXNzYCwgZXRjLikKLSBPcHRpb25hbCBzYW5kYm94ZWQgYnJvd3NlcgoKKipOb3Qgc2FuZGJveGVkOioqCi0gR2F0ZXdheSBwcm9jZXNzIGl0c2VsZgotIEVsZXZhdGVkIGV4ZWMgKGB0b29scy5lbGV2YXRlZGApIHJ1bnMgb24gaG9zdAoKLS0tCgojIyBSZW1vdGUgQWNjZXNzICYgRGVwbG95bWVudAoKIyMjIFJlbW90ZSBBY2Nlc3MgT3B0aW9ucwoKKipTb3VyY2U6KiogW1JlbW90ZSBBY2Nlc3MgR3VpZGVdKGh0dHBzOi8vZG9jcy5vcGVuY2xhdy5haS9nYXRld2F5L3JlbW90ZSkKCjEuICoqQWx3YXlzLW9uIEdhdGV3YXkgaW4gdGFpbG5ldCoqIChWUFMgb3IgaG9tZSBzZXJ2ZXIpCiAgIC0gQmVzdCBVWDogS2VlcCBgZ2F0ZXdheS5iaW5kOiAibG9vcGJhY2siYCArIFRhaWxzY2FsZSBTZXJ2ZQogICAKMi4gKipIb21lIGRlc2t0b3AgcnVucyBHYXRld2F5LCBsYXB0b3AgaXMgcmVtb3RlIGNvbnRyb2wqKgogICAtIFVzZSBtYWNPUyBhcHAncyAiUmVtb3RlIG92ZXIgU1NIIiBtb2RlCgozLiAqKkxhcHRvcCBydW5zIEdhdGV3YXksIHJlbW90ZSBhY2Nlc3MgZnJvbSBvdGhlciBtYWNoaW5lcyoqCiAgIC0gU1NIIHR1bm5lbCBvciBUYWlsc2NhbGUgU2VydmUKCiMjIyBTU0ggVHVubmVsCgpgYGBiYXNoCnNzaCAtTiAtTCAxODc4OToxMjcuMC4wLjE6MTg3ODkgdXNlckBob3N0CmBgYAoKV2l0aCB0dW5uZWwgdXAsIENMSSBjb21tYW5kcyByZWFjaCByZW1vdGUgZ2F0ZXdheSB2aWEgYHdzOi8vMTI3LjAuMC4xOjE4Nzg5YC4KCiMjIyBSZW1vdGUgQ0xJIERlZmF1bHRzCgpgYGBqc29uNQp7CiAgZ2F0ZXdheTogewogICAgbW9kZTogInJlbW90ZSIsCiAgICByZW1vdGU6IHsKICAgICAgdXJsOiAid3M6Ly8xMjcuMC4wLjE6MTg3ODkiLAogICAgICB0b2tlbjogInlvdXItdG9rZW4iLAogICAgfSwKICB9LAp9CmBgYAoKIyMjIFRhaWxzY2FsZSBJbnRlZ3JhdGlvbgoKKipTb3VyY2U6KiogW1RhaWxzY2FsZSBHdWlkZV0oaHR0cHM6Ly9kb2NzLm9wZW5jbGF3LmFpL2dhdGV3YXkvdGFpbHNjYWxlKQoKRW5hYmxlIFRhaWxzY2FsZSBleHBvc3VyZToKYGBganNvbjUKewogIGdhdGV3YXk6IHsKICAgIGF1dGg6IHsKICAgICAgYWxsb3dUYWlsc2NhbGU6IHRydWUsCiAgICB9LAogIH0sCn0KYGBgCgotLS0KCiMjIFRyb3VibGVzaG9vdGluZwoKIyMjIEZpcnN0IDYwIFNlY29uZHMgRGlhZ25vc3RpYwoKKipTb3VyY2U6KiogW1Ryb3VibGVzaG9vdGluZyBHdWlkZV0oaHR0cHM6Ly9kb2NzLm9wZW5jbGF3LmFpL2hlbHAvdHJvdWJsZXNob290aW5nKQoKUnVuIHRoaXMgZXhhY3QgbGFkZGVyIGluIG9yZGVyOgoKYGBgYmFzaApvcGVuY2xhdyBzdGF0dXMKb3BlbmNsYXcgc3RhdHVzIC0tYWxsCm9wZW5jbGF3IGdhdGV3YXkgcHJvYmUKb3BlbmNsYXcgZ2F0ZXdheSBzdGF0dXMKb3BlbmNsYXcgZG9jdG9yCm9wZW5jbGF3IGNoYW5uZWxzIHN0YXR1cyAtLXByb2JlCm9wZW5jbGF3IGxvZ3MgLS1mb2xsb3cKYGBgCgojIyMgQ29tbW9uIElzc3VlcwoKKipTb3VyY2U6KiogW0ZBUV0oaHR0cHM6Ly9kb2NzLm9wZW5jbGF3LmFpL2hlbHAvZmFxKQoKfCBJc3N1ZSB8IFNvbHV0aW9uIHwKfC0tLS0tLS18LS0tLS0tLS0tLXwKfCAiZHJvcCBndWlsZCBtZXNzYWdlIChtZW50aW9uIHJlcXVpcmVkKSIgfCBNZW50aW9uIGdhdGluZyBibG9ja2VkIG1lc3NhZ2UgaW4gRGlzY29yZCB8CnwgInBhaXJpbmcgcmVxdWVzdCIgfCBTZW5kZXIgaXMgdW5hcHByb3ZlZCwgd2FpdGluZyBmb3IgRE0gcGFpcmluZyBhcHByb3ZhbCB8CnwgImJsb2NrZWQiIC8gImFsbG93bGlzdCIgfCBTZW5kZXIsIHJvb20sIG9yIGdyb3VwIGlzIGZpbHRlcmVkIHwKfCAiZGV2aWNlIGlkZW50aXR5IHJlcXVpcmVkIiB8IEhUVFAvbm9uLXNlY3VyZSBjb250ZXh0IGNhbm5vdCBjb21wbGV0ZSBkZXZpY2UgYXV0aCB8CnwgInVuYXV0aG9yaXplZCIgLyByZWNvbm5lY3QgbG9vcCB8IFdyb25nIHRva2VuL3Bhc3N3b3JkIG9yIGF1dGggbW9kZSBtaXNtYXRjaCB8CnwgR2F0ZXdheSBzdGFydCBibG9ja2VkIHwgU2V0IGBnYXRld2F5Lm1vZGU9bG9jYWxgIHwKCiMjIyBSZXNldCBFdmVyeXRoaW5nCgpgYGBiYXNoCm9wZW5jbGF3IHJlc2V0CmBgYAoKLS0tCgojIyBBZHZhbmNlZCBDb25maWd1cmF0aW9uCgojIyMgTWluaW1hbCBDb25maWcKCioqU291cmNlOioqIFtDb25maWd1cmF0aW9uIEV4YW1wbGVzXShodHRwczovL2RvY3Mub3BlbmNsYXcuYWkvZ2F0ZXdheS9jb25maWd1cmF0aW9uLWV4YW1wbGVzKQoKYGBganNvbjUKewogIGFnZW50OiB7IHdvcmtzcGFjZTogIn4vLm9wZW5jbGF3L3dvcmtzcGFjZSIgfSwKICBjaGFubmVsczogeyB3aGF0c2FwcDogeyBhbGxvd0Zyb206IFsiKzE1NTU1NTUwMTIzIl0gfSB9LAp9CmBgYAoKIyMjIFJlY29tbWVuZGVkIFN0YXJ0ZXIgQ29uZmlnCgpgYGBqc29uNQp7CiAgaWRlbnRpdHk6IHsKICAgIG5hbWU6ICJDbGF3ZCIsCiAgICB0aGVtZTogImhlbHBmdWwgYXNzaXN0YW50IiwKICAgIGVtb2ppOiAi8J+mniIsCiAgfSwKICBhZ2VudDogewogICAgd29ya3NwYWNlOiAifi8ub3BlbmNsYXcvd29ya3NwYWNlIiwKICAgIG1vZGVsOiB7IHByaW1hcnk6ICJhbnRocm9waWMvY2xhdWRlLXNvbm5ldC00LTUiIH0sCiAgfSwKICBjaGFubmVsczogewogICAgd2hhdHNhcHA6IHsKICAgICAgYWxsb3dGcm9tOiBbIisxNTU1NTU1MDEyMyJdLAogICAgICBncm91cHM6IHsgIioiOiB7IHJlcXVpcmVNZW50aW9uOiB0cnVlIH0gfSwKICAgIH0sCiAgfSwKfQpgYGAKCiMjIyBTZXNzaW9uIENvbmZpZ3VyYXRpb24KCioqU291cmNlOioqIFtTZXNzaW9uIE1hbmFnZW1lbnRdKGh0dHBzOi8vZG9jcy5vcGVuY2xhdy5haS9jb25jZXB0cy9zZXNzaW9uKQoKYGBganNvbjUKewogIHNlc3Npb246IHsKICAgIHNjb3BlOiAicGVyLXNlbmRlciIsCiAgICByZXNldDogewogICAgICBtb2RlOiAiZGFpbHkiLAogICAgICBhdEhvdXI6IDQsCiAgICAgIGlkbGVNaW51dGVzOiA2MCwKICAgIH0sCiAgICByZXNldFRyaWdnZXJzOiBbIi9uZXciLCAiL3Jlc2V0Il0sCiAgICBtYWludGVuYW5jZTogewogICAgICBtb2RlOiAid2FybiIsCiAgICAgIHBydW5lQWZ0ZXI6ICIzMGQiLAogICAgICBtYXhFbnRyaWVzOiA1MDAsCiAgICB9LAogIH0sCn0KYGBgCgojIyMgUm91dGluZyAmIFF1ZXVlIENvbmZpZ3VyYXRpb24KCmBgYGpzb241CnsKICByb3V0aW5nOiB7CiAgICBncm91cENoYXQ6IHsKICAgICAgbWVudGlvblBhdHRlcm5zOiBbIkBvcGVuY2xhdyIsICJvcGVuY2xhdyJdLAogICAgICBoaXN0b3J5TGltaXQ6IDUwLAogICAgfSwKICAgIHF1ZXVlOiB7CiAgICAgIG1vZGU6ICJjb2xsZWN0IiwKICAgICAgZGVib3VuY2VNczogMTAwMCwKICAgICAgY2FwOiAyMCwKICAgICAgZHJvcDogInN1bW1hcml6ZSIsCiAgICB9LAogIH0sCn0KYGBgCgotLS0KCiMjIFdlYmhvb2tzCgojIyMgRW5hYmxlIFdlYmhvb2tzCgoqKlNvdXJjZToqKiBbV2ViaG9va3MgR3VpZGVdKGh0dHBzOi8vZG9jcy5vcGVuY2xhdy5haS9hdXRvbWF0aW9uL3dlYmhvb2spCgpgYGBqc29uNQp7CiAgaG9va3M6IHsKICAgIGVuYWJsZWQ6IHRydWUsCiAgICB0b2tlbjogInNoYXJlZC1zZWNyZXQiLAogICAgcGF0aDogIi9ob29rcyIsCiAgICBhbGxvd2VkQWdlbnRJZHM6IFsiaG9va3MiLCAibWFpbiJdLAogIH0sCn0KYGBgCgojIyMgV2ViaG9vayBFbmRwb2ludHMKCioqUE9TVCAvaG9va3Mvd2FrZSoqCmBgYGpzb24KeyAKICAidGV4dCI6ICJTeXN0ZW0gbGluZSIsIAogICJtb2RlIjogIm5vdyIgIC8vIG5vdyB8IG5leHQtaGVhcnRiZWF0Cn0KYGBgCgoqKlBPU1QgL2hvb2tzL2FnZW50KioKYGBganNvbgp7CiAgIm1lc3NhZ2UiOiAiUnVuIHRoaXMiLAogICJuYW1lIjogIkVtYWlsIiwKICAiYWdlbnRJZCI6ICJob29rcyIsCiAgInNlc3Npb25LZXkiOiAiaG9vazplbWFpbDptc2ctMTIzIiwKICAid2FrZU1vZGUiOiAibm93IiwKICAiZGVsaXZlciI6IHRydWUsCiAgImNoYW5uZWwiOiAibGFzdCIsCiAgInRvIjogIisxNTU1MTIzNDU2NyIsCiAgIm1vZGVsIjogIm9wZW5haS9ncHQtNS4yLW1pbmkiLAogICJ0aGlua2luZyI6ICJsb3ciLAogICJ0aW1lb3V0U2Vjb25kcyI6IDEyMAp9CmBgYAoKLS0tCgojIyBTa2lsbHMgJiBDbGF3SHViCgojIyMgU2tpbGxzIExvY2F0aW9ucyAoUHJlY2VkZW5jZSkKCioqU291cmNlOioqIFtTa2lsbHMgR3VpZGVdKGh0dHBzOi8vZG9jcy5vcGVuY2xhdy5haS90b29scy9za2lsbHMpCgoxLiAqKldvcmtzcGFjZSBza2lsbHM6KiogYDx3b3Jrc3BhY2U+L3NraWxsc2AgKGhpZ2hlc3QpCjIuICoqTWFuYWdlZCBza2lsbHM6KiogYH4vLm9wZW5jbGF3L3NraWxsc2AKMy4gKipCdW5kbGVkIHNraWxsczoqKiBTaGlwcGVkIHdpdGggaW5zdGFsbCAobG93ZXN0KQoKIyMjIENsYXdIdWIgQ29tbWFuZHMKCmBgYGJhc2gKIyBJbnN0YWxsIGEgc2tpbGwKY2xhd2h1YiBpbnN0YWxsIDxza2lsbC1zbHVnPgoKIyBVcGRhdGUgYWxsIHNraWxscwpjbGF3aHViIHVwZGF0ZSAtLWFsbAoKIyBTeW5jIHNraWxscwpjbGF3aHViIHN5bmMgLS1hbGwKYGBgCgojIyMgU2tpbGwgRm9ybWF0CgpgYGBtYXJrZG93bgotLS0KbmFtZTogbXktc2tpbGwKZGVzY3JpcHRpb246IFdoYXQgdGhpcyBza2lsbCBkb2VzCnVzZXItaW52b2NhYmxlOiB0cnVlCmRpc2FibGUtbW9kZWwtaW52b2NhdGlvbjogZmFsc2UKLS0tCgpJbnN0cnVjdGlvbnMgaGVyZS4uLgpgYGAKCi0tLQoKIyMgQmVzdCBQcmFjdGljZXMgU3VtbWFyeQoKIyMjIERvJ3MKCuKchSBVc2UgYG9wZW5jbGF3IGRhc2hib2FyZGAgZm9yIGZhc3Rlc3QgZmlyc3QgY2hhdCAgCuKchSBDcmVhdGUgYEhFQVJUQkVBVC5tZGAgZm9yIHBlcmlvZGljIHRhc2tzICAK4pyFIFdyaXRlIGltcG9ydGFudCBpbmZvIHRvIGBNRU1PUlkubWRgIG9yIGRhaWx5IGxvZ3MgIArinIUgRW5hYmxlIHNlY3VyZSBETSBtb2RlIChgZG1TY29wZWApIGZvciBtdWx0aS11c2VyIHNldHVwcyAgCuKchSBVc2Ugc2FuZGJveGluZyBmb3IgdW50cnVzdGVkIGlucHV0cyAgCuKchSBTZXQgdXAgbW9kZWwgZmFsbGJhY2tzIGZvciByZWxpYWJpbGl0eSAgCuKchSBVc2UgY3JvbiBmb3IgZXhhY3QgdGltaW5nLCBoZWFydGJlYXQgZm9yIHBlcmlvZGljIGF3YXJlbmVzcyAgCuKchSBSdW4gYG9wZW5jbGF3IGRvY3RvcmAgYmVmb3JlIHRyb3VibGVzaG9vdGluZyAgCuKchSBLZWVwIGF1dGggcHJvZmlsZXMgaW4gYGF1dGgtcHJvZmlsZXMuanNvbmAgKG5vdCBjb25maWcpICAK4pyFIFVzZSBTU0ggdHVubmVscyBvciBUYWlsc2NhbGUgZm9yIHJlbW90ZSBhY2Nlc3MgIAoKIyMjIERvbid0cwoK4p2MIERvbid0IHNoYXJlIGBhZ2VudERpcmAgYWNyb3NzIGFnZW50cyAoY2F1c2VzIGF1dGgvc2Vzc2lvbiBjb2xsaXNpb25zKSAgCuKdjCBEb24ndCBzdG9yZSBzZWNyZXRzIGluIGBvcGVuY2xhdy5qc29uYCAodXNlIGBhdXRoLXByb2ZpbGVzLmpzb25gKSAgCuKdjCBEb24ndCBlbmFibGUgYGRtUG9saWN5OiAib3BlbiJgIHdpdGhvdXQgdW5kZXJzdGFuZGluZyBzZWN1cml0eSBpbXBsaWNhdGlvbnMgIArinYwgRG9uJ3QgcG9sbCBgc3ViYWdlbnRzIGxpc3RgIGluIGxvb3BzICh1c2UgcHVzaC1iYXNlZCBjb21wbGV0aW9uKSAgCuKdjCBEb24ndCBydW4gbXVsdGlwbGUgZ2F0ZXdheXMgcGVyIGhvc3QgKHVzZSBpc29sYXRlZCBwcm9maWxlcyBpZiBuZWVkZWQpICAKCi0tLQoKIyMgUmVzb3VyY2VzCgojIyMgT2ZmaWNpYWwgRG9jdW1lbnRhdGlvbgotICoqTWFpbiBEb2NzOioqIGh0dHBzOi8vZG9jcy5vcGVuY2xhdy5haQotICoqTExNcy50eHQgSW5kZXg6KiogaHR0cHM6Ly9kb2NzLm9wZW5jbGF3LmFpL2xsbXMudHh0Ci0gKipHaXRIdWI6KiogaHR0cHM6Ly9naXRodWIuY29tL29wZW5jbGF3L29wZW5jbGF3Ci0gKipDbGF3SHViOioqIGh0dHBzOi8vY2xhd2h1Yi5jb20KCiMjIyBLZXkgRG9jdW1lbnRhdGlvbiBQYWdlcwotIFtHZXR0aW5nIFN0YXJ0ZWRdKGh0dHBzOi8vZG9jcy5vcGVuY2xhdy5haS9zdGFydC9nZXR0aW5nLXN0YXJ0ZWQpCi0gW0NvbmZpZ3VyYXRpb24gUmVmZXJlbmNlXShodHRwczovL2RvY3Mub3BlbmNsYXcuYWkvZ2F0ZXdheS9jb25maWd1cmF0aW9uLXJlZmVyZW5jZSkKLSBbQ0xJIFJlZmVyZW5jZV0oaHR0cHM6Ly9kb2NzLm9wZW5jbGF3LmFpL2NsaS9pbmRleCkKLSBbRkFRXShodHRwczovL2RvY3Mub3BlbmNsYXcuYWkvaGVscC9mYXEpCi0gW1Ryb3VibGVzaG9vdGluZ10oaHR0cHM6Ly9kb2NzLm9wZW5jbGF3LmFpL2hlbHAvdHJvdWJsZXNob290aW5nKQoKIyMjIENvbW11bml0eQotIEdpdEh1YiBEaXNjdXNzaW9uczogaHR0cHM6Ly9naXRodWIuY29tL29wZW5jbGF3L29wZW5jbGF3L2Rpc2N1c3Npb25zCi0gR2l0SHViIElzc3VlczogaHR0cHM6Ly9naXRodWIuY29tL29wZW5jbGF3L29wZW5jbGF3L2lzc3VlcwoKLS0tCgoqRG9jdW1lbnQgY29tcGlsZWQgZnJvbSBvZmZpY2lhbCBPcGVuQ2xhdyBkb2N1bWVudGF0aW9uIGFzIG9mIEZlYnJ1YXJ5IDIyLCAyMDI2LioKCipGb3IgdGhlIGxhdGVzdCBpbmZvcm1hdGlvbiwgYWx3YXlzIHJlZmVyIHRvIGh0dHBzOi8vZG9jcy5vcGVuY2xhdy5haSoK", + "uploadedAt": "2026-02-22T00:05:51Z" + } + ] + }, + { + "id": "d53d6e30-0afc-4060-8105-d1046c7cb594", + "title": "Phase 9: Polish and integration", + "description": null, + "type": "task", + "status": "done", + "priority": "medium", + "project_id": "a1b2c3d4-0001-0000-0000-000000000001", + "sprint_id": "b2c3d4e5-0002-0000-0000-000000000002", + "created_at": "2026-02-22 02:57:36+00", + "updated_at": "2026-02-23 20:12:16.671626+00", + "created_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "updated_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [], + "tags": [], + "attachments": [] + }, + { + "id": "f328d12d-d045-4b67-af46-d02c15975b1f", + "title": "Research: Simon Hoiberg X Thread on AI/Startups", + "description": "**URL:** https://x.com/SimonHoiberg/status/2025918084591063322\n\n**Status:** ✅ Research completed using Tavily AI search\n\n**Key Findings:**\n- Simon Hoiberg runs lean AI-powered startup (4 people + 9 AI agents)\n- Target: $2M ARR in 2025\n- AI agents handle content creation, team comms, business ops\n- Uses Discord for AI agent team collaboration\n- Philosophy: Speed > perfection, real solutions > flashy demos\n\n**Attachment:** simon-hoiberg-research.md (full summary with sources)\n\n**Note:** Original X thread was not directly accessible, but related content was found and summarized.", + "type": "research", + "status": "review", + "priority": "medium", + "project_id": "a1b2c3d4-0001-0000-0000-000000000001", + "sprint_id": "b2c3d4e5-0002-0000-0000-000000000002", + "created_at": "2026-02-23 20:04:35.861039+00", + "updated_at": "2026-02-23 20:15:28.498387+00", + "created_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "updated_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [], + "tags": [ + "research", + "x-thread", + "ai", + "startups" + ], + "attachments": [ + { + "id": "e5223f81-e0ae-4065-8018-a3a73db952b8", + "name": "simon-hoiberg-research.md", + "size": 1502, + "type": "text/markdown", + "dataUrl": "data:text/markdown;base64,IyBTaW1vbiBIb2liZXJnOiBBSSBBZ2VudCBUZWFtICYgTGVhbiBTdGFydHVwIFJlc2VhcmNoCgoqKk9yaWdpbmFsIFVSTDoqKiBodHRwczovL3guY29tL1NpbW9uSG9pYmVyZy9zdGF0dXMvMjAyNTkxODA4NDU5MTA2MzMyMgoqKlJlc2VhcmNoIERhdGU6KiogMjAyNi0wMi0yMwoqKlNvdXJjZToqKiBUYXZpbHkgQUkgU2VhcmNoCgotLS0KCiMjIEtleSBJbnNpZ2h0cwoKIyMjIEFJIEFnZW50IFRlYW0gU3RydWN0dXJlClNpbW9uIEhvaWJlcmcgcnVucyBhICoqbGVhbiBBSS1wb3dlcmVkIHN0YXJ0dXAqKiB3aXRoIGEgdGVhbSBvZiBBSSBhZ2VudHM6Ci0gKioyMDIzOioqIDExIHBlb3BsZQotICoqMjAyNDoqKiA5IHBlb3BsZSAgCi0gKioyMDI1OioqIDQgcGVvcGxlICsgQUkgYWdlbnRzCgpIZSBoYXMgKio5IEFJIGFnZW50cyBpbiBhIERpc2NvcmQqKiB3aXRoIG5hbWVzIGFuZCBwcm9maWxlIGltYWdlcyB0aGF0IGNhbiB0YWxrIHRvIGVhY2ggb3RoZXIgYW5kIHRvIGhpbS4KCiMjIyBCdXNpbmVzcyBNZXRyaWNzCi0gKipUYXJnZXQ6KiogJDJNIEFSUiBpbiAyMDI1Ci0gKipDdXJyZW50IHJldmVudWUgc3RyZWFtczoqKgogIC0gRnJlZWxhbmNpbmc6ICskMzAwSy95ZWFyCiAgLSBTYWFTOiAkMjBLL21vbnRoCiAgLSBFLUJvb2tzOiAkNEsvbW9udGgKICAtIFlvdVR1YmU6ICQ2Sy9tb250aAoKIyMjIEFJIEFnZW50IEFwcGxpY2F0aW9ucwoxLiAqKkNvbnRlbnQgQ3JlYXRpb246KiogQUkgYWdlbnRzIHJlc2VhcmNoLCB3cml0ZSwgYW5kIHB1Ymxpc2ggU0VPLW9wdGltaXplZCBibG9nIHBvc3RzCjIuICoqVGVhbSBDb21tdW5pY2F0aW9uOioqIEFnZW50cyBjb2xsYWJvcmF0ZSBpbiBEaXNjb3JkCjMuICoqQnVzaW5lc3MgT3BlcmF0aW9uczoqKiBIYW5kbGVzIHRhc2tzIGFjcm9zcyB0aGUgYnVzaW5lc3MKCiMjIyBQaGlsb3NvcGh5Ci0gU3BlZWQgdG8gbWFya2V0ID4gcGVyZmVjdGlvbgotIEFJIHRoYXQgc29sdmVzIHJlYWwgcHJvYmxlbXMgPiBmbGFzaHkgZGVtb3MKLSBJbnRlZ3JhdGlvbiB3aXRoIGV4aXN0aW5nIHdvcmtmbG93cyA+IHN0YW5kYWxvbmUgdG9vbHMKLSBMZWFuIHRlYW0gZW5hYmxlZCBieSBBSSBhdXRvbWF0aW9uCgotLS0KCiMjIFJlbGF0ZWQgUmVzb3VyY2VzCi0gWCBQcm9maWxlOiBodHRwczovL3guY29tL1NpbW9uSG9pYmVyZwotIEhpZ2hsaWdodHM6IGh0dHBzOi8veC5jb20vU2ltb25Ib2liZXJnL2hpZ2hsaWdodHMKLSBBSSBBZ2VudCBUZWFtIFBvc3Q6IGh0dHBzOi8vd3d3LnRocmVhZHMuY29tL0BzaW1vbmhvaWJlcmcvcG9zdC9EUEdzUl9IRFNYYS8KLSBZb3VUdWJlIFR1dG9yaWFsOiBodHRwczovL3d3dy55b3V0dWJlLmNvbS93YXRjaD92PUhtMERadGlLVUk4CgotLS0KCipOb3RlOiBPcmlnaW5hbCBYIHRocmVhZCBjb250ZW50IHdhcyBub3QgYWNjZXNzaWJsZSBkdWUgdG8gcHJpdmFjeSByZXN0cmljdGlvbnMuIFRoaXMgc3VtbWFyeSBpcyBjb21waWxlZCBmcm9tIHJlbGF0ZWQgcHVibGljIHNvdXJjZXMuKgo=", + "uploadedAt": "2026-02-23T20:15:11Z" + } + ] + }, + { + "id": "85a4c1ee-8cf1-417f-b979-0b516304dfa6", + "title": "Phase 1: Connect Mission Control to Supabase", + "description": null, + "type": "task", + "status": "done", + "priority": "high", + "project_id": "a1b2c3d4-0001-0000-0000-000000000001", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-22 02:57:34+00", + "updated_at": "2026-02-23 17:32:38.142417+00", + "created_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "updated_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [], + "tags": [], + "attachments": [ + { + "id": "c54ab916-89ac-496f-bf51-8c78e90a0d36", + "name": "mission-control-refactor-plan.md", + "size": 13108, + "type": "text/markdown", + "dataUrl": "data:text/markdown;base64,IyBNaXNzaW9uIENvbnRyb2wgUmVmYWN0b3IgUGxhbgoKKipTdGF0dXM6KiogUGxhbm5pbmcgIAoqKkdvYWw6KiogVHJhbnNmb3JtIE1pc3Npb24gQ29udHJvbCBpbnRvIGEgZGFzaGJvYXJkIHRoYXQgcmVhZHMgZnJvbSBnYW50dC1ib2FyZCdzIFN1cGFiYXNlIGRhdGEgIAoqKkFwcHJvYWNoOioqIFBoYXNlZCBpbXBsZW1lbnRhdGlvbgoKLS0tCgojIyBDdXJyZW50IFN0YXRlCgojIyMgZ2FudHQtYm9hcmQgKFNvdXJjZSBvZiBUcnV0aCkKLSAqKkRhdGFiYXNlOioqIFN1cGFiYXNlIChxbmF0Y2hyamxwZWhpaWp3dHJlaCkKLSAqKlRhYmxlczoqKiB0YXNrcywgcHJvamVjdHMsIHNwcmludHMsIHVzZXJzLCBtZXRhCi0gKipGZWF0dXJlczoqKiBGdWxsIENSVUQsIGthbmJhbiwgYXV0aCwgQ0xJIHRvb2xzCi0gKipEYXRhOioqIFJlYWwgdGFza3MsIHJlYWwgcHJvamVjdHMKCiMjIyBNaXNzaW9uIENvbnRyb2wgKEN1cnJlbnQpCi0gKipTdG9yYWdlOioqIEZpbGUtYmFzZWQgKHRhc2tEYi50cykgLSBTRVBBUkFURSBmcm9tIGdhbnR0LWJvYXJkCi0gKipEYXRhOioqIEhhcmRjb2RlZC9zdGF0aWMgdmFsdWVzIGluIFVJCi0gKipQYWdlczoqKiBEYXNoYm9hcmQsIFRhc2tzIChkdXBsaWNhdGVzIGdhbnR0LWJvYXJkKSwgQ2FsZW5kYXIsIERvY3VtZW50cywgVG9vbHMsIFByb2plY3RzLCBBY3Rpdml0eSwgTWlzc2lvbgotICoqUHJvYmxlbToqKiBUd28gdGFzayBzeXN0ZW1zID0gY29uZnVzaW9uLCBubyByZWFsIGRhdGEKCi0tLQoKIyMgVGFyZ2V0IEFyY2hpdGVjdHVyZQoKYGBgCuKUjOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUkArilIIgICAgICAgICAgICAgICAgICAgIE1JU1NJT04gQ09OVFJPTCAgICAgICAgICAgICAgICAgICAgICDilIIK4pSCICAgICAgICAgICAgICAoUmVhZC1Pbmx5IERhc2hib2FyZCBWaWV3KSAgICAgICAgICAgICAgICAg4pSCCuKUnOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUpArilIIgIOKUjOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUkCAg4pSM4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSQICDilIzilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilJAgIOKUggrilIIgIOKUgiAgIE1pc3Npb24gICAg4pSCICDilIIgICAgIEtQSXMgICAgIOKUgiAg4pSCICBDYWxlbmRhciAgICDilIIgIOKUggrilIIgIOKUgiAgIFByb2dyZXNzICAg4pSCICDilIIgIChmcm9tIERCKSAgIOKUgiAg4pSCICAoZXh0ZXJuYWwpICDilIIgIOKUggrilIIgIOKUlOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUmCAg4pSU4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSYICDilJTilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilJggIOKUggrilIIgIOKUjOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUkCAg4pSM4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSQICDilIzilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilJAgIOKUggrilIIgIOKUgiAgIEFjdGl2aXR5ICAg4pSCICDilIIgIERvY3VtZW50cyAgIOKUgiAg4pSCICAgIFRvb2xzICAgICDilIIgIOKUggrilIIgIOKUgiAgIFN0cmVhbSAgICAg4pSCICDilIIgICAobm90ZXMpICAgIOKUgiAg4pSCICAobGlua3MpICAgICDilIIgIOKUggrilIIgIOKUlOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUmCAg4pSU4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSYICDilJTilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilJggIOKUggrilJTilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilJgKICAgICAgICAgICAgICAgICAgICAgICAgICAg4pSCCiAgICAgICAgICAgICAgICAgICAgICAgICAgIOKUgiBGZXRjaGVzIHZpYSBBUEkKICAgICAgICAgICAgICAgICAgICAgICAgICAg4pa8CuKUjOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUkArilIIgICAgICAgICAgICAgICAgICAgIGdhbnR0LWJvYXJkICAgICAgICAgICAgICAgICAgICAgICAgICDilIIK4pSCICAgICAgICAgICAgICAoU291cmNlIG9mIFRydXRoIC0gU3VwYWJhc2UpICAgICAgICAgICAgICAg4pSCCuKUnOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUpArilIIgIFRhYmxlczogdGFza3MsIHByb2plY3RzLCBzcHJpbnRzLCB1c2VycywgbWV0YSAgICAgICAgIOKUggrilIIgIEZlYXR1cmVzOiBGdWxsIENSVUQsIEthbmJhbiwgQ0xJIHRvb2xzLCBBdXRoICAgICAgICAgIOKUggrilJTilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilJgKYGBgCgotLS0KCiMjIFBoYXNlIEJyZWFrZG93bgoKIyMjIFBoYXNlIDE6IEZvdW5kYXRpb24gLSBDb25uZWN0IHRvIFJlYWwgRGF0YQoqKlByaW9yaXR5OioqIENyaXRpY2FsICAKKipFc3RpbWF0ZWQgVGltZToqKiAyLTMgaG91cnMgIAoqKkJsb2NrczoqKiBBbGwgb3RoZXIgcGhhc2VzCgoqKlRhc2tzOioqCjEuIFsgXSBBZGQgU3VwYWJhc2UgY2xpZW50IHRvIE1pc3Npb24gQ29udHJvbAogICAtIENvcHkgYC5lbnYubG9jYWxgIGZyb20gZ2FudHQtYm9hcmQKICAgLSBJbnN0YWxsIGBAc3VwYWJhc2Uvc3VwYWJhc2UtanNgCiAgIC0gQ3JlYXRlIGBsaWIvc3VwYWJhc2UvY2xpZW50LnRzYAoKMi4gWyBdIENyZWF0ZSBkYXRhIGZldGNoaW5nIGxheWVyCiAgIC0gYGxpYi9kYXRhL3Rhc2tzLnRzYCAtIGZldGNoIGZyb20gZ2FudHQtYm9hcmQgU3VwYWJhc2UKICAgLSBgbGliL2RhdGEvcHJvamVjdHMudHNgIC0gZmV0Y2ggcHJvamVjdHMKICAgLSBgbGliL2RhdGEvc3RhdHMudHNgIC0gY2FsY3VsYXRlIEtQSXMgZnJvbSByZWFsIGRhdGEKCjMuIFsgXSBVcGRhdGUgRGFzaGJvYXJkIHBhZ2UgKGFwcC9wYWdlLnRzeCkKICAgLSBSZXBsYWNlIGhhcmRjb2RlZCBLUElzIHdpdGggcmVhbCBjYWxjdWxhdGlvbnM6CiAgICAgLSBBY3RpdmUgVGFza3M6IGBTRUxFQ1QgQ09VTlQoKikgRlJPTSB0YXNrcyBXSEVSRSBzdGF0dXMgIT0gJ2RvbmUnYAogICAgIC0gR29hbHMgUHJvZ3Jlc3M6IENhbGN1bGF0ZSBmcm9tIHByb2plY3QgY29tcGxldGlvbgogICAgIC0gQXBwcyBCdWlsdDogQ291bnQgb2YgcHJvamVjdHMgb3IgbWV0YSB2YWx1ZQogICAtIEtlZXAgbWlzc2lvbiBzdGF0ZW1lbnQgYmFubmVyCiAgIC0gS2VlcCBwcm9ncmVzcyBiYXJzIChidXQgcG9wdWxhdGUgd2l0aCByZWFsICUpCgo0LiBbIF0gUmVtb3ZlIGZpbGUtYmFzZWQgc3RvcmFnZQogICAtIERlbGV0ZSBgbGliL3NlcnZlci90YXNrRGIudHNgCiAgIC0gRGVsZXRlIG9yIHJlcHVycG9zZSBgYXBwL2FwaS90YXNrcy9yb3V0ZS50c2AKCioqU3VjY2VzcyBDcml0ZXJpYToqKgotIERhc2hib2FyZCBzaG93cyByZWFsIHRhc2sgY291bnRzIGZyb20gZ2FudHQtYm9hcmQKLSBObyBtb3JlIGhhcmRjb2RlZCAiMTIgYWN0aXZlIHRhc2tzIgotIFBhZ2UgbG9hZHMgd2l0aCBkYXRhIGZyb20gU3VwYWJhc2UKCi0tLQoKIyMjIFBoYXNlIDI6IFRhc2tzIFBhZ2UgLSBUcmFuc2Zvcm0gdG8gT3ZlcnZpZXcKKipQcmlvcml0eToqKiBIaWdoICAKKipFc3RpbWF0ZWQgVGltZToqKiAxLTIgaG91cnMgIAoqKkJsb2NrczoqKiBOb25lCgoqKlRhc2tzOioqCjEuIFsgXSBSZXBsYWNlIGthbmJhbiB3aXRoIHN1bW1hcnkgdmlldwogICAtIERvbid0IGR1cGxpY2F0ZSBnYW50dC1ib2FyZCdzIGthbmJhbgogICAtIFNob3c6ICJIaWdoIFByaW9yaXR5IFRhc2tzIiBsaXN0ICh0b3AgNSkKICAgLSBTaG93OiAiUmVjZW50bHkgQ29tcGxldGVkIiAobGFzdCA1IGRvbmUpCiAgIC0gU2hvdzogIlRoaXMgV2VlaydzIEZvY3VzIiAodGFza3MgaW4tcHJvZ3Jlc3MpCgoyLiBbIF0gQWRkIHF1aWNrIGFjdGlvbnMKICAgLSAiT3BlbiBpbiBnYW50dC1ib2FyZCIgYnV0dG9uCiAgIC0gTGlua3MgdG8gc3BlY2lmaWMgdmlld3MgKHNwcmludCwgcHJvamVjdCBmaWx0ZXJzKQoKMy4gWyBdIFNob3cgdGFzayBzdGF0cwogICAtIFRvdGFsIHRhc2tzIGJ5IHN0YXR1cyAocGllIGNoYXJ0IG9yIGNvdW50ZXJzKQogICAtIFRhc2tzIGJ5IHByb2plY3QgKGJyZWFrZG93bikKICAgLSBPdmVyZHVlIHRhc2tzIGNvdW50CgoqKlN1Y2Nlc3MgQ3JpdGVyaWE6KioKLSBUYXNrcyBwYWdlIGdpdmVzIGV4ZWN1dGl2ZSBvdmVydmlldywgbm90IGthbmJhbgotIENsZWFyIGxpbmtzIHRvIGdhbnR0LWJvYXJkIGZvciBhY3R1YWwgdGFzayBtYW5hZ2VtZW50Ci0gUmVhbCBkYXRhIGZyb20gU3VwYWJhc2UKCi0tLQoKIyMjIFBoYXNlIDM6IE1pc3Npb24gUGFnZSAtIEVuaGFuY2VkIFByb2dyZXNzIFRyYWNraW5nCioqUHJpb3JpdHk6KiogSGlnaCAgCioqRXN0aW1hdGVkIFRpbWU6KiogMi0zIGhvdXJzCgoqKlRhc2tzOioqCjEuIFsgXSBEZWZpbmUgIk1pc3Npb24gTWV0cmljcyIKICAgLSBSZXRpcmVtZW50IGdvYWwgcHJvZ3Jlc3MgKG1hbnVhbCBpbnB1dCBvciBjYWxjdWxhdGVkKQogICAtIGlPUyBhcHBzIHBvcnRmb2xpbyAoY291bnQgZnJvbSBwcm9qZWN0cyBuYW1lZCAiaU9TICoiKQogICAtIFNpZGUgaHVzdGxlIHJldmVudWUgKG1hbnVhbCBpbnB1dCkKICAgLSBUcmF2ZWwgZnVuZCBwcm9ncmVzcyAobWFudWFsKQoKMi4gWyBdIENyZWF0ZSBtaXNzaW9uIHByb2dyZXNzIHZpc3VhbGl6YXRpb24KICAgLSBMYXJnZXIsIG1vcmUgZGV0YWlsZWQgcHJvZ3Jlc3MgYmFycwogICAtIE1pbGVzdG9uZSBtYXJrZXJzIChlLmcuLCAiQXBwICM1IHB1Ymxpc2hlZCIsICJGaXJzdCAkMUsgTVJSIikKICAgLSBUaW1lbGluZSBvZiBhY2hpZXZlbWVudHMgKGZyb20gY29tcGxldGVkIHRhc2tzKQoKMy4gWyBdIEFkZCBtaXNzaW9uLXJlbGF0ZWQgdGFza3MKICAgLSBQdWxsIHRhc2tzIHRhZ2dlZCB3aXRoICJtaXNzaW9uIiBvciAicmV0aXJlbWVudCIKICAgLSBTaG93IG5leHQgc3RlcHMgdG93YXJkIGdvYWxzCgoqKlN1Y2Nlc3MgQ3JpdGVyaWE6KioKLSBNaXNzaW9uIHBhZ2UgYmVjb21lcyB0aGUgIm5vcnRoIHN0YXIiIHZpZXcKLSBDb25uZWN0cyBkYWlseSB0YXNrcyAoZ2FudHQtYm9hcmQpIHRvIGJpZyBnb2FscwotIE1vdGl2YXRpbmcsIHZpc3VhbCBwcm9ncmVzcyB0cmFja2luZwoKLS0tCgojIyMgUGhhc2UgNDogQ2FsZW5kYXIgSW50ZWdyYXRpb24KKipQcmlvcml0eToqKiBNZWRpdW0gIAoqKkVzdGltYXRlZCBUaW1lOioqIDMtNCBob3VycwoKKipUYXNrczoqKgoxLiBbIF0gQ29ubmVjdCB0byBBcHBsZSBDYWxlbmRhcgogICAtIFVzZSBleGlzdGluZyBjYWxlbmRhci1hc3Npc3RhbnQgc2tpbGwKICAgLSBGZXRjaCB1cGNvbWluZyBldmVudHMKICAgLSBTaG93IGluIE1pc3Npb24gQ29udHJvbCBjYWxlbmRhciB2aWV3CgoyLiBbIF0gQ29ubmVjdCBjYWxlbmRhciB0byB0YXNrcwogICAtIFNob3cgdGFzayBkdWUgZGF0ZXMgb24gY2FsZW5kYXIKICAgLSBIaWdobGlnaHQgZGF5cyB3aXRoIGRlYWRsaW5lcwogICAtIFNob3cgc3ByaW50IGRhdGVzCgozLiBbIF0gQWRkIGNhbGVuZGFyIGV2ZW50cyBmcm9tIHRhc2tzCiAgIC0gV2hlbiB0YXNrIGhhcyBkdWVfZGF0ZSwgc2hvdyBvbiBjYWxlbmRhcgogICAtIFNwcmludCBzdGFydC9lbmQgZGF0ZXMKCioqU3VjY2VzcyBDcml0ZXJpYToqKgotIENhbGVuZGFyIHNob3dzIHJlYWwgZXZlbnRzIGZyb20gQXBwbGUgQ2FsZW5kYXIKLSBUYXNrIGRlYWRsaW5lcyB2aXNpYmxlCi0gU3ByaW50IHRpbWVsaW5lcyB2aXNpYmxlCgotLS0KCiMjIyBQaGFzZSA1OiBEb2N1bWVudHMgUGFnZQoqKlByaW9yaXR5OioqIE1lZGl1bSAgCioqRXN0aW1hdGVkIFRpbWU6KiogMi0zIGhvdXJzCgoqKlRhc2tzOioqCjEuIFsgXSBEZWZpbmUgZG9jdW1lbnQgdHlwZXMKICAgLSBNZWV0aW5nIG5vdGVzCiAgIC0gRGVjaXNpb24gbG9ncwogICAtIFByb2plY3QgYnJpZWZzCiAgIC0gUmVzZWFyY2ggZG9jcwoKMi4gWyBdIENyZWF0ZSBkb2N1bWVudCBzdG9yYWdlCiAgIC0gU3RvcmUgaW4gU3VwYWJhc2UgKG5ldyB0YWJsZTogYG1pc3Npb24tZG9jdW1lbnRzYCkKICAgLSBPciBmaWxlLWJhc2VkIGluIGBkYXRhL2RvY3VtZW50cy9gCgozLiBbIF0gQnVpbGQgZG9jdW1lbnQgdmlld2VyL2NyZWF0b3IKICAgLSBMaXN0IGFsbCBkb2N1bWVudHMKICAgLSBNYXJrZG93biBlZGl0b3IKICAgLSBUYWdnaW5nIHN5c3RlbQogICAtIExpbmtzIHRvIHJlbGF0ZWQgdGFza3MvcHJvamVjdHMKCioqU3VjY2VzcyBDcml0ZXJpYToqKgotIENhbiBjcmVhdGUsIGVkaXQsIHZpZXcgZG9jdW1lbnRzCi0gRG9jdW1lbnRzIGxpbmtlZCB0byB0YXNrcy9wcm9qZWN0cwotIFNlYXJjaGFibGUKCi0tLQoKIyMjIFBoYXNlIDY6IFRvb2xzIFBhZ2UKKipQcmlvcml0eToqKiBMb3cgIAoqKkVzdGltYXRlZCBUaW1lOioqIDEtMiBob3VycwoKKipUYXNrczoqKgoxLiBbIF0gQ3JlYXRlIHRvb2xzIGRpcmVjdG9yeQogICAtIExpbmtzIHRvIGFsbCB3ZWIgYXBwcyAoZ2FudHQtYm9hcmQsIGJsb2ctYmFja3VwLCBldGMuKQogICAtIFF1aWNrIGxpbmtzIHRvIENMSSB0b29scwogICAtIExpbmtzIHRvIGV4dGVybmFsIHRvb2xzIChHaXRlYSwgU3VwYWJhc2UgZGFzaGJvYXJkKQoKMi4gWyBdIEFkZCB1dGlsaXR5IHRvb2xzCiAgIC0gVGFzayBxdWljay1hZGQgKGNyZWF0ZXMgaW4gZ2FudHQtYm9hcmQpCiAgIC0gVGltZXIvcG9tb2Rvcm8KICAgLSBEYWlseSBicmllZmluZyBnZW5lcmF0b3IKCjMuIFsgXSBTdGF0dXMgaW5kaWNhdG9ycwogICAtIFNob3cgaWYgc2VydmljZXMgYXJlIHVwIChncmVlbi9yZWQgZG90cykKICAgLSBMYXN0IGRlcGxveW1lbnQgdGltZQoKKipTdWNjZXNzIENyaXRlcmlhOioqCi0gU2luZ2xlIHBhZ2Ugd2l0aCBhbGwgdG9vbCBsaW5rcwotIFF1aWNrIGFjdGlvbnMgZm9yIGNvbW1vbiB0YXNrcwotIFN0YXR1cyBhd2FyZW5lc3MKCi0tLQoKIyMjIFBoYXNlIDc6IEFjdGl2aXR5IEZlZWQKKipQcmlvcml0eToqKiBNZWRpdW0gIAoqKkVzdGltYXRlZCBUaW1lOioqIDItMyBob3VycwoKKipUYXNrczoqKgoxLiBbIF0gQ3JlYXRlIGFjdGl2aXR5IGxvZwogICAtIE5ldyB0YWJsZTogYGFjdGl2aXR5LWxvZ2AgaW4gU3VwYWJhc2UKICAgLSBPciByZWFkIGZyb20gZXhpc3RpbmcgdGFzayBjb21tZW50cy91cGRhdGVzCgoyLiBbIF0gVHJhY2sgYWN0aXZpdHkgdHlwZXMKICAgLSBUYXNrIGNyZWF0ZWQvY29tcGxldGVkCiAgIC0gUHJvamVjdCBtaWxlc3RvbmUgcmVhY2hlZAogICAtIEZpbGUgYXR0YWNoZWQKICAgLSBOb3RlIGNyZWF0ZWQKCjMuIFsgXSBCdWlsZCBhY3Rpdml0eSBzdHJlYW0KICAgLSBDaHJvbm9sb2dpY2FsIGZlZWQKICAgLSBGaWx0ZXIgYnkgdHlwZQogICAtIEZpbHRlciBieSBwcm9qZWN0CgoqKlN1Y2Nlc3MgQ3JpdGVyaWE6KioKLSBSZWFsIGFjdGl2aXR5IGZlZWQgKG5vdCBoYXJkY29kZWQpCi0gU2hvd3Mgd2hhdCdzIGhhcHBlbmluZyBhY3Jvc3MgYWxsIHRvb2xzCi0gTGlua3MgdG8gc3BlY2lmaWMgdGFza3MvcHJvamVjdHMKCi0tLQoKIyMjIFBoYXNlIDg6IFByb2plY3RzIFBhZ2UKKipQcmlvcml0eToqKiBNZWRpdW0gIAoqKkVzdGltYXRlZCBUaW1lOioqIDItMyBob3VycwoKKipUYXNrczoqKgoxLiBbIF0gQ3JlYXRlIHByb2plY3Qgb3ZlcnZpZXcKICAgLSBMaXN0IGFsbCBwcm9qZWN0cyBmcm9tIGdhbnR0LWJvYXJkCiAgIC0gU2hvdyBzdGF0cyBwZXIgcHJvamVjdDoKICAgICAtIFRvdGFsIHRhc2tzCiAgICAgLSBDb21wbGV0ZWQgdGFza3MKICAgICAtIEluLXByb2dyZXNzIHRhc2tzCiAgICAgLSBTcHJpbnQgc3RhdHVzCgoyLiBbIF0gUHJvamVjdCBkZXRhaWwgdmlldwogICAtIENsaWNrIHByb2plY3Qg4oaSIHNlZSBkZXRhaWxzCiAgIC0gUmVjZW50IGFjdGl2aXR5IGZvciB0aGF0IHByb2plY3QKICAgLSBUZWFtIG1lbWJlcnMgKGZyb20gdGFzayBhc3NpZ25lZXMpCgozLiBbIF0gUHJvamVjdCBoZWFsdGggaW5kaWNhdG9ycwogICAtIE9uIHRyYWNrIC8gYXQgcmlzayAvIGJlaGluZAogICAtIEJhc2VkIG9uIHNwcmludCBkYXRlcyB2cyB0YXNrIGNvbXBsZXRpb24KCioqU3VjY2VzcyBDcml0ZXJpYToqKgotIEFsbCBwcm9qZWN0cyB2aXNpYmxlIHdpdGggcmVhbCBzdGF0cwotIEhlYWx0aCBpbmRpY2F0b3JzIGhlbHAgcHJpb3JpdGl6ZQotIExpbmtzIHRvIGdhbnR0LWJvYXJkIGZpbHRlcmVkIHZpZXdzCgotLS0KCiMjIyBQaGFzZSA5OiBQb2xpc2ggJiBJbnRlZ3JhdGlvbgoqKlByaW9yaXR5OioqIExvdyAgCioqRXN0aW1hdGVkIFRpbWU6KiogMy00IGhvdXJzCgoqKlRhc2tzOioqCjEuIFsgXSBBZGQgbmF2aWdhdGlvbiBpbXByb3ZlbWVudHMKICAgLSBCcmVhZGNydW1icwogICAtIEJldHRlciBzaWRlYmFyIG9yZ2FuaXphdGlvbgogICAtIFF1aWNrIHNlYXJjaCBhY3Jvc3MgYWxsIGNvbnRlbnQKCjIuIFsgXSBNb2JpbGUgcmVzcG9uc2l2ZW5lc3MKICAgLSBFbnN1cmUgYWxsIHBhZ2VzIHdvcmsgb24gbW9iaWxlCiAgIC0gVG91Y2gtZnJpZW5kbHkga2FuYmFuIChpZiBrZWVwaW5nKQoKMy4gWyBdIFJlYWwtdGltZSB1cGRhdGVzCiAgIC0gU3VwYWJhc2UgcmVhbHRpbWUgc3Vic2NyaXB0aW9ucwogICAtIERhc2hib2FyZCB1cGRhdGVzIHdoZW4gdGFza3MgY2hhbmdlCgo0LiBbIF0gQXV0aGVudGljYXRpb24KICAgLSBVc2Ugc2FtZSBhdXRoIGFzIGdhbnR0LWJvYXJkCiAgIC0gU2luZ2xlIHNpZ24tb24gZXhwZXJpZW5jZQoKKipTdWNjZXNzIENyaXRlcmlhOioqCi0gUG9saXNoZWQsIHByb2Zlc3Npb25hbCBmZWVsCi0gV29ya3Mgc2VhbWxlc3NseSB3aXRoIGdhbnR0LWJvYXJkCi0gUmVhbC10aW1lIGRhdGEgdXBkYXRlcwoKLS0tCgojIyBEYXRhIEZsb3cKCmBgYArilIzilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilJAgICAgIOKUjOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUkArilIIgICBVc2VyIEFjdGlvbiAgICDilILilIDilIDilIDilIDilrbilIIgIGdhbnR0LWJvYXJkICAgICDilIIK4pSCICAoY3JlYXRlcyB0YXNrKSAg4pSCICAgICDilIIgICAoU3VwYWJhc2UpICAgICDilIIK4pSU4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSYICAgICDilJTilIDilIDilIDilIDilIDilIDilIDilIDilKzilIDilIDilIDilIDilIDilIDilIDilIDilIDilJgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIOKUggogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg4pSCIFJlYWwtdGltZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg4pSCIHVwZGF0ZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg4pa8CiAgICAgICAgICAgICAgICAgICAgICAgICDilIzilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilJAKICAgICAgICAgICAgICAgICAgICAgICAgIOKUgiBNaXNzaW9uIENvbnRyb2wgIOKUggogICAgICAgICAgICAgICAgICAgICAgICAg4pSCICAoZGFzaGJvYXJkKSAgICAg4pSCCiAgICAgICAgICAgICAgICAgICAgICAgICDilIIgIC0gS1BJcyB1cGRhdGUgICDilIIKICAgICAgICAgICAgICAgICAgICAgICAgIOKUgiAgLSBBY3Rpdml0eSBsb2cgIOKUggogICAgICAgICAgICAgICAgICAgICAgICAg4pSCICAtIFByb2dyZXNzIGJhcnMg4pSCCiAgICAgICAgICAgICAgICAgICAgICAgICDilJTilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilJgKYGBgCgotLS0KCiMjIFRlY2huaWNhbCBJbXBsZW1lbnRhdGlvbiBOb3RlcwoKIyMjIFN1cGFiYXNlIENvbm5lY3Rpb24KCioqU2hhcmVkIENyZWRlbnRpYWxzOioqCmBgYGVudgpORVhUX1BVQkxJQ19TVVBBQkFTRV9VUkw9aHR0cHM6Ly9xbmF0Y2hyamxwZWhpaWp3dHJlaC5zdXBhYmFzZS5jbwpORVhUX1BVQkxJQ19TVVBBQkFTRV9BTk9OX0tFWT1leUpoYkdjaU9pSklVekkxTmlJc0luUjVjQ0k2SWtwWFZDSjkuZXlKcGMzTWlPaUp6ZFhCaFltRnpaU0lzSW5KbFppSTZJbkZ1WVhSamFISnFiSEJsYUdscGFuZDBjbVZvSWl3aWNtOXNaU0k2SW1GdWIyNGlMQ0pwWVhRaU9qRTNOekUyTkRBME16WXNJbVY0Y0NJNk1qQTROekl4TmpRek5uMC40N1hPTXJRQnpjUUVoNzFwaFFmbFBvTzR2NzlKazNyZnQ3QkM3MktIRHZBClNVUEFCQVNFX1NFUlZJQ0VfUk9MRV9LRVk9ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnBjM01pT2lKemRYQmhZbUZ6WlNJc0luSmxaaUk2SW5GdVlYUmphSEpxYkhCbGFHbHBhbmQwY21Wb0lpd2ljbTlzWlNJNkluTmxjblpwWTJWZmNtOXNaU0lzSW1saGRDSTZNVGMzTVRZME1EUXpOaXdpWlhod0lqb3lNRGczTWpFMk5ETTJmUS5ySG9jM05mTDU5UzRsZWpVNC1BclN6b3gxa3JRa1FHLVRuZlhiNnNzbG0wCmBgYAoKKipDbGllbnQgU2V0dXA6KioKYGBgdHlwZXNjcmlwdAovLyBsaWIvc3VwYWJhc2UvY2xpZW50LnRzCmltcG9ydCB7IGNyZWF0ZUJyb3dzZXJDbGllbnQgfSBmcm9tICdAc3VwYWJhc2Uvc3NyJwoKZXhwb3J0IGNvbnN0IGNyZWF0ZUNsaWVudCA9ICgpID0+CiAgY3JlYXRlQnJvd3NlckNsaWVudCgKICAgIHByb2Nlc3MuZW52Lk5FWFRfUFVCTElDX1NVUEFCQVNFX1VSTCEsCiAgICBwcm9jZXNzLmVudi5ORVhUX1BVQkxJQ19TVVBBQkFTRV9BTk9OX0tFWSEKICApCmBgYAoKIyMjIFRhYmxlIEFjY2VzcwoKTWlzc2lvbiBDb250cm9sIHNob3VsZCB1c2UgKipyZWFkLW9ubHkqKiBxdWVyaWVzIGZvciBtb3N0IG9wZXJhdGlvbnM6CgpgYGB0eXBlc2NyaXB0Ci8vIFJlYWQgdGFza3MgKGRhc2hib2FyZCkKY29uc3QgeyBkYXRhOiB0YXNrcyB9ID0gYXdhaXQgc3VwYWJhc2UKICAuZnJvbSgndGFza3MnKQogIC5zZWxlY3QoJyonKQogIC5uZXEoJ3N0YXR1cycsICdkb25lJykKCi8vIFJlYWQgcHJvamVjdHMKY29uc3QgeyBkYXRhOiBwcm9qZWN0cyB9ID0gYXdhaXQgc3VwYWJhc2UKICAuZnJvbSgncHJvamVjdHMnKQogIC5zZWxlY3QoJyonKQpgYGAKCkZvciBtb2RpZmljYXRpb25zIChpZiBhbnkpLCByb3V0ZSB0aHJvdWdoIGdhbnR0LWJvYXJkJ3MgQVBJIG9yIHJlZGlyZWN0IHVzZXIgdGhlcmUuCgotLS0KCiMjIFN1Y2Nlc3MgTWV0cmljcwoKLSBbIF0gRGFzaGJvYXJkIHNob3dzIHJlYWwgZGF0YSAobm90IGhhcmRjb2RlZCkKLSBbIF0gVGFzayBjb3VudHMgbWF0Y2ggZ2FudHQtYm9hcmQKLSBbIF0gQ2FsZW5kYXIgc2hvd3MgcmVhbCBldmVudHMKLSBbIF0gQWN0aXZpdHkgZmVlZCBzaG93cyByZWFsIGFjdGlvbnMKLSBbIF0gTm8gZHVwbGljYXRlIHRhc2sgY3JlYXRpb24gaW50ZXJmYWNlcwotIFsgXSBDbGVhciBkaXN0aW5jdGlvbjogZ2FudHQtYm9hcmQgPSB3b3JrLCBNaXNzaW9uIENvbnRyb2wgPSBvdmVydmlldwotIFsgXSBTaW5nbGUgc291cmNlIG9mIHRydXRoIChnYW50dC1ib2FyZCBTdXBhYmFzZSkKCi0tLQoKIyMgRnV0dXJlIEVuaGFuY2VtZW50cyAoUG9zdC1MYXVuY2gpCgotIFsgXSBQdXNoIG5vdGlmaWNhdGlvbnMgZm9yIHRhc2sgZGVhZGxpbmVzCi0gWyBdIFdlZWtseSBlbWFpbCBkaWdlc3QKLSBbIF0gSW50ZWdyYXRpb24gd2l0aCBtb3JlIGNhbGVuZGFycyAoR29vZ2xlKQotIFsgXSBNb2JpbGUgYXBwIChQV0EpCi0gWyBdIEFJLXBvd2VyZWQgaW5zaWdodHMgKCJZb3UncmUgZmFsbGluZyBiZWhpbmQgb24gaU9TIGFwcHMiKQotIFsgXSBCdWRnZXQvZXhwZW5zZSB0cmFja2luZyBsaW5rZWQgdG8gcHJvamVjdHMKLSBbIF0gVGltZSB0cmFja2luZyBwZXIgdGFzawoKLS0tCgojIyBPcGVuIFF1ZXN0aW9ucwoKMS4gU2hvdWxkIE1pc3Npb24gQ29udHJvbCBoYXZlIEFOWSB3cml0ZSBvcGVyYXRpb25zLCBvciBiZSBzdHJpY3RseSByZWFkLW9ubHk/CjIuIFNob3VsZCB3ZSBhZGQgYSBuZXcgdGFibGUgYG1pc3Npb24tbWV0cmljc2AgZm9yIHJldGlyZW1lbnQgcHJvZ3Jlc3MgdHJhY2tpbmc/CjMuIFNob3VsZCBkb2N1bWVudHMgYmUgaW4gU3VwYWJhc2Ugb3Igc3RheSBmaWxlLWJhc2VkPwo0LiBEbyB3ZSBrZWVwIHRoZSAiQWRkIFRhc2siIGJ1dHRvbiBpbiBNaXNzaW9uIENvbnRyb2wgb3IgcmVtb3ZlIGl0IGVudGlyZWx5PwoKLS0tCgoqKk5leHQgU3RlcDoqKiBEZWNpZGUgb24gUGhhc2UgMSBzdGFydCBhbmQgYmVnaW4gaW1wbGVtZW50YXRpb24uCg==", + "uploadedAt": "2026-02-22T02:57:58Z" + } + ] + }, + { + "id": "66bdce3c-0cd0-444f-8f45-995b036c5f15", + "title": "Phase 5: Documents page", + "description": null, + "type": "task", + "status": "done", + "priority": "medium", + "project_id": "a1b2c3d4-0001-0000-0000-000000000001", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-22 02:57:35+00", + "updated_at": "2026-02-23 17:32:38.389509+00", + "created_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "updated_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [], + "tags": [], + "attachments": [] + }, + { + "id": "21373b2e-e486-4b0b-9842-849d2422cd7f", + "title": "Phase 6: Tools page with quick links", + "description": null, + "type": "task", + "status": "done", + "priority": "medium", + "project_id": "a1b2c3d4-0001-0000-0000-000000000001", + "sprint_id": "b2c3d4e5-0002-0000-0000-000000000002", + "created_at": "2026-02-22 02:57:35+00", + "updated_at": "2026-02-23 20:11:15.425165+00", + "created_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "updated_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [], + "tags": [], + "attachments": [] + }, + { + "id": "b7c5fe59-109e-4437-b88b-7fe9874cc862", + "title": "Phase 2: Transform Tasks page to overview", + "description": null, + "type": "task", + "status": "done", + "priority": "medium", + "project_id": "a1b2c3d4-0001-0000-0000-000000000001", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-22 02:57:34+00", + "updated_at": "2026-02-23 17:32:38.679266+00", + "created_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "updated_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [], + "tags": [], + "attachments": [] + }, + { + "id": "8f478969-e83e-4399-b61f-37ca4d6b1d35", + "title": "Add Sprint Archive/History page", + "description": null, + "type": "task", + "status": "done", + "priority": "medium", + "project_id": "a1b2c3d4-0001-0000-0000-000000000001", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-22 02:57:36+00", + "updated_at": "2026-02-23 17:32:38.960954+00", + "created_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "updated_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [], + "tags": [], + "attachments": [] + }, + { + "id": "e6249c1d-cf05-48e4-ae80-530337b1dc9f", + "title": "Add Sprint functionality to Gantt Board", + "description": null, + "type": "task", + "status": "done", + "priority": "urgent", + "project_id": "a1b2c3d4-0002-0000-0000-000000000002", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-20 05:30:17.029+00", + "updated_at": "2026-02-21 17:41:53.330535+00", + "created_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "updated_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [], + "tags": [ + "Web Projects" + ], + "attachments": [] + }, + { + "id": "55065eae-5eac-4064-ada4-3c7f07899ceb", + "title": "Phase 7: Activity feed from real data", + "description": null, + "type": "task", + "status": "done", + "priority": "medium", + "project_id": "a1b2c3d4-0001-0000-0000-000000000001", + "sprint_id": "b2c3d4e5-0002-0000-0000-000000000002", + "created_at": "2026-02-22 02:57:35+00", + "updated_at": "2026-02-23 20:11:37.050585+00", + "created_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "updated_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [], + "tags": [], + "attachments": [] + }, + { + "id": "b82674ce-e8a4-41ea-8e9c-99f39f47d78d", + "title": "Review X thread - OpenClaw Mission Control System by Julian Goldie SEO", + "description": "Comprehensive guide to OpenClaw Mission Control System\n\nSource: X thread by @JulianGoldieSEO\nURL: https://x.com/juliangoldieseo/status/2025299921713426465?s=46\n\nFull markdown summary attached with:\n- Key features (Dashboard, Kanban, Skill Marketplace, etc.)\n- Benefits for beginners and advanced users\n- Use cases\n- FAQ section\n- Getting started resources\n\nIncludes link to AI Success Lab for additional learning.", + "type": "research", + "status": "done", + "priority": "medium", + "project_id": "a1b2c3d4-0001-0000-0000-000000000001", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-22 04:33:37+00", + "updated_at": "2026-02-23 17:32:36.974657+00", + "created_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "updated_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [], + "tags": [], + "attachments": [ + { + "id": "336906e2-72b4-45da-a56d-7952f282e96b", + "name": "openclaw-mission-control-guide.md", + "size": 5554, + "type": "text/markdown", + "dataUrl": "data:text/markdown;base64,IyBPcGVuQ2xhdyBNaXNzaW9uIENvbnRyb2wgU3lzdGVtOiBDb21wbGV0ZSBHdWlkZQoKKipTb3VyY2U6KiogWCBBcnRpY2xlIGJ5IFtKdWxpYW4gR29sZGllIFNFT10oaHR0cHM6Ly94LmNvbS9KdWxpYW5Hb2xkaWVTRU8pICAKKipEYXRlOioqIEZlYnJ1YXJ5IDIxLCAyMDI2ICAKKipVUkw6KiogaHR0cHM6Ly94LmNvbS9qdWxpYW5nb2xkaWVzZW8vc3RhdHVzLzIwMjUyOTk5MjE3MTM0MjY0NjU/cz00NgoKLS0tCgojIyBPdmVydmlldwoKKipPcGVuQ2xhdyBNaXNzaW9uIENvbnRyb2wgU3lzdGVtKiogaXMgYSBjb21wcmVoZW5zaXZlIEFJIGF1dG9tYXRpb24gcGxhdGZvcm0gdGhhdCBicmluZ3Mgb3JkZXIsIHNwZWVkLCBhbmQgc2ltcGxpY2l0eSB0byBldmVyeWRheSBhdXRvbWF0aW9uIHRhc2tzLiBJdCB0cmFuc2Zvcm1zIHNjYXR0ZXJlZCBhdXRvbWF0aW9uIGludG8gYSBzdHJ1Y3R1cmVkLCB2aXN1YWwgc3lzdGVtIHdpdGggY29tcGxldGUgdmlzaWJpbGl0eSBhbmQgb3ZlcnNpZ2h0LgoKLS0tCgojIyBLZXkgRmVhdHVyZXMKCiMjIyAxLiAqKlVuaWZpZWQgRGFzaGJvYXJkKioKLSBTZWUgYWxsIGFnZW50cyBpbiBvbmUgY2VudHJhbGl6ZWQgZGFzaGJvYXJkCi0gVHJhY2sgdGFza3MgdmlzdWFsbHkgdGhyb3VnaCBLYW5iYW4gYm9hcmRzCi0gV2F0Y2ggYWdlbnRzIGNvbW11bmljYXRlIHdpdGggZWFjaCBvdGhlcgotIEFwcHJvdmUgYWN0aW9ucyBpbiByZWFsLXRpbWUKLSBSdW4gZXZlcnl0aGluZyBvbiBhdXRvcGlsb3QKCiMjIyAyLiAqKldvcmtmbG93IEJvYXJkcyAoS2FuYmFuIFN5c3RlbSkqKgpUYXNrcyBmbG93IHRocm91Z2ggYSBuYXR1cmFsIHByb2dyZXNzaW9uOgotICoqQmFja2xvZyoqIOKGkiBUYXNrcyB3YWl0aW5nIHRvIHN0YXJ0Ci0gKipJbiBQcm9ncmVzcyoqIOKGkiBBY3RpdmUgd29yawotICoqUmV2aWV3Kiog4oaSIEF3YWl0aW5nIG92ZXJzaWdodC9hcHByb3ZhbAotICoqRG9uZSoqIOKGkiBDb21wbGV0ZWQgdGFza3MKClRoaXMgc3RydWN0dXJlIHJlbW92ZXMgZ3Vlc3N3b3JrIGFuZCBwcm92aWRlcyBjbGVhciB2aXNpYmlsaXR5IGludG8gd2hhdCBpcyBiZWluZyB3b3JrZWQgb24sIHdoYXQgbmVlZHMgYXR0ZW50aW9uLCBhbmQgd2hhdCBoYXMgYmVlbiBjb21wbGV0ZWQuCgojIyMgMy4gKipTa2lsbCBNYXJrZXRwbGFjZSoqCi0gSW5zdGFsbCBuZXcgYXV0b21hdGlvbiBjYXBhYmlsaXRpZXMgd2l0aCBzaW5nbGUgYWN0aW9uCi0gTm8gY3VzdG9tIHNjcmlwdGluZyByZXF1aXJlZAotIFNraWxscyBpbmNsdWRlOgogIC0gV3JpdGluZyBoZWxwZXJzCiAgLSBEYXRhIHByb2Nlc3NvcnMKICAtIEF1dG9tYXRpb24gdHJpZ2dlcnMKICAtIFBsYW5uaW5nIHRvb2xzCiAgLSBBZHZhbmNlZCBBSSBjYXBhYmlsaXRpZXMKLSBTeXN0ZW0gZXZvbHZlcyBpbiByZWFsLXRpbWUgd2l0aCBjb25zdGFudCBzdHJlYW0gb2YgbmV3IHRvb2xzCgojIyMgNC4gKipCb2FyZCBHcm91cHMqKgotIE9yZ2FuaXplIG11bHRpcGxlIHdvcmtmbG93cyBpbnRvIGxhYmVsZWQgc2VjdGlvbnMKLSBQcmV2ZW50cyBpbnRlcmZhY2Ugb3ZlcndoZWxtCi0gU3VwcG9ydHM6CiAgLSBDb250ZW50IHBpcGVsaW5lcwogIC0gQnVzaW5lc3MgdGFza3MKICAtIFBsYW5uaW5nIHN5c3RlbXMKICAtIFBlcnNvbmFsIHJvdXRpbmVzCiAgLSBSZXNlYXJjaCBwcm9qZWN0cwotIEJ1aWx0IGZvciBsb25nLXRlcm0gc2NhbGFiaWxpdHkKCiMjIyA1LiAqKkFwcHJvdmFsIExheWVycyoqCi0gRGVzaWduYXRlIHdoaWNoIGFjdGlvbnMgcmVxdWlyZSBtYW51YWwgcmV2aWV3Ci0gUGF1c2Ugc2Vuc2l0aXZlIHRhc2tzIHVudGlsIGFwcHJvdmVkCi0gUHJldmVudHMgcHJlbWF0dXJlIG9yIGluY29ycmVjdCBleGVjdXRpb24KLSBCYWxhbmNlcyBzcGVlZCBhbmQgc2FmZXR5Ci0gU3VpdGFibGUgZm9yIGJvdGggYmVnaW5uZXJzIGFuZCBhZHZhbmNlZCB1c2VycwoKIyMjIDYuICoqR2F0ZXdheSBTdXBwb3J0IChEaXN0cmlidXRlZCBOZXR3b3JrKSoqCi0gUnVuIHRhc2tzIGFjcm9zcyBtdWx0aXBsZSBlbnZpcm9ubWVudHM6CiAgLSBMaWdodHdlaWdodCB0YXNrcyBvbiBsYXB0b3AKICAtIEhlYXZ5IHRhc2tzIG9uIHNlcnZlcgogIC0gQ29udGludW91cyB0YXNrcyBvbiBjbG91ZCBpbmZyYXN0cnVjdHVyZQotIFNlYW1sZXNzIHN3aXRjaGluZyBiZXR3ZWVuIGdhdGV3YXlzCi0gVW5pZmllZCBkYXNoYm9hcmQgdmlldyBhY3Jvc3MgYWxsIGVudmlyb25tZW50cwotIFNjYWxhYmxlIHdpdGhvdXQgdGVjaG5pY2FsIGhlYWRhY2hlcwoKIyMjIDcuICoqTGl2ZSBBY3Rpdml0eSBTdHJlYW0qKgotIFJlYWwtdGltZSB2aXNpYmlsaXR5IG9mIGFsbCBhY3Rpb25zCi0gV2F0Y2ggdGFza3MgZXhlY3V0ZQotIFNlZSBhZ2VudHMgY29tbXVuaWNhdGUKLSBUcmFjayB3b3JrZmxvdyBwcm9ncmVzcwotIE1vbml0b3IgYXBwcm92YWwgdXBkYXRlcwotIEluc3RhbnQgdHJvdWJsZXNob290aW5nIChpc3N1ZXMgYXBwZWFyIGluIHJlYWwtdGltZSwgbm90IGhpZGRlbiBpbiBsb2dzKQoKIyMjIDguICoqQ3VzdG9tIERhc2hib2FyZHMqKgotIERlc2NyaWJlIHlvdXIgaWRlYWwgZGFzaGJvYXJkIGluIG5hdHVyYWwgbGFuZ3VhZ2UKLSBPcGVuQ2xhdyBjcmVhdGVzIGl0IGF1dG9tYXRpY2FsbHkKLSBDdXN0b21pemFibGUgZWxlbWVudHM6CiAgLSBMYXlvdXQgY2hhbmdlcwogIC0gQ3VzdG9tIHdpZGdldHMKICAtIE1vZGlmaWVkIHBhbmVscwogIC0gQ29sb3IgYWRqdXN0bWVudHMKICAtIE5ldyBjb250cm9sIHNlY3Rpb25zCi0gRGFzaGJvYXJkIGJlY29tZXMgZXh0ZW5zaW9uIG9mIHdvcmtmbG93CgotLS0KCiMjIEJlbmVmaXRzCgojIyMgRm9yIEJlZ2lubmVycwotIFNpbXBsZSwgdmlzdWFsIGludGVyZmFjZQotIE5vIGNvZGluZyByZXF1aXJlZAotIE5hdHVyYWwgbGFuZ3VhZ2UgaW5zdHJ1Y3Rpb25zCi0gQ2xlYXIgdGFzayBwcm9ncmVzc2lvbgotIENvbmZpZGVuY2UgdGhyb3VnaCB0cmFuc3BhcmVuY3kKCiMjIyBGb3IgQWR2YW5jZWQgVXNlcnMKLSBDb21wbGV4IG9wZXJhdGlvbmFsIGludGVyZmFjZXMKLSBEaXN0cmlidXRlZCBnYXRld2F5IHN1cHBvcnQKLSBDdXN0b20gZGFzaGJvYXJkIGNyZWF0aW9uCi0gU2NhbGFibGUgd29ya2Zsb3cgbWFuYWdlbWVudAotIFJlYWwtdGltZSBtb25pdG9yaW5nCgojIyMgS2V5IE91dGNvbWVzCi0gKipDbGFyaXR5IG92ZXIgY29uZnVzaW9uKiog4oCUIEtub3cgZXhhY3RseSB3aGF0IGFnZW50cyBhcmUgZG9pbmcKLSAqKlN0cnVjdHVyZWQgd29ya2Zsb3dzKiog4oCUIERlc2lnbiBwcm9jZXNzZXMgaW5zdGVhZCBvZiBtYW5hZ2luZyBpc29sYXRlZCBhY3Rpb25zCi0gKipSZWR1Y2VkIG1pY3JvbWFuYWdlbWVudCoqIOKAlCBPdmVyc2VlIHByb2Nlc3NlcyB0aGF0IHJ1biBzbW9vdGhseQotICoqQXV0b21hdGlvbiBhcyBsZXZlcmFnZSoqIOKAlCBOb3QgZXh0cmEgd29yaywgYnV0IGEgZm9yY2UgbXVsdGlwbGllcgotICoqVG90YWwgb3ZlcnNpZ2h0Kiog4oCUIENvbXBsZXRlIHZpc2liaWxpdHkgaW50byBhdXRvbWF0aW9uIGVudmlyb25tZW50CgotLS0KCiMjIFVzZSBDYXNlcwoKLSBEYWlseSB3b3JrIGF1dG9tYXRpb24KLSBDb250ZW50IGNyZWF0aW9uIHBpcGVsaW5lcwotIEJ1c2luZXNzIHRhc2sgbWFuYWdlbWVudAotIFBlcnNvbmFsIHJvdXRpbmUgb3B0aW1pemF0aW9uCi0gUmVzZWFyY2ggcHJvamVjdCBjb29yZGluYXRpb24KLSBNdWx0aS1lbnZpcm9ubWVudCB3b3JrZmxvd3MKLSBUZWFtIGNvbGxhYm9yYXRpb24KCi0tLQoKIyMgR2V0dGluZyBTdGFydGVkCgojIyMgT2ZmaWNpYWwgUmVzb3VyY2VzCi0gKipNYWluIFdlYnNpdGU6KiogaHR0cHM6Ly93d3cuZ2V0b3BlbmNsYXcuYWkvCi0gKipTZXR1cDoqKiBGcmVlIHRvIHNldCB1cAotICoqU3VwcG9ydDoqKiBETSBASnVsaWFuR29sZGllU0VPIGZvciBTT1AgKFN0YW5kYXJkIE9wZXJhdGluZyBQcm9jZWR1cmUpCgojIyMgQ29tbXVuaXR5ICYgTGVhcm5pbmcKLSAqKkFJIFN1Y2Nlc3MgTGFiOioqIGh0dHBzOi8vYWlzdWNjZXNzbGFianVsaWFuZ29sZGllLmNvbS8KICAtIFN0ZXAtYnktc3RlcCB3b3JrZmxvd3MKICAtIFRlbXBsYXRlcyBhbmQgdHV0b3JpYWxzCiAgLSBBSSBhdXRvbWF0aW9uIGZvciBjb250ZW50LCBtYXJrZXRpbmcsIHdvcmtmbG93cwogIC0gRnJlZSB0byBqb2luCgotLS0KCiMjIEZyZXF1ZW50bHkgQXNrZWQgUXVlc3Rpb25zCgoqKlE6IFdoYXQgcHJvYmxlbSBkb2VzIE1pc3Npb24gQ29udHJvbCBzb2x2ZT8qKiAgCkE6IEl0IHR1cm5zIHNjYXR0ZXJlZCBhdXRvbWF0aW9uIGludG8gYSBzdHJ1Y3R1cmVkLCB2aXN1YWwgc3lzdGVtIHdpdGggY29tcGxldGUgdmlzaWJpbGl0eS4KCioqUTogRG9lcyBpdCB3b3JrIGZvciBub24tdGVjaG5pY2FsIHBlb3BsZT8qKiAgCkE6IFllcy4gVGhlIGludGVyZmFjZSBpcyBzaW1wbGUsIHZpc3VhbCwgYW5kIGVhc3kgdG8gdW5kZXJzdGFuZC4KCioqUTogSG93IGRvZXMgaXQgaGVscCB3aXRoIGF1dG9tYXRpb24gZ3Jvd3RoPyoqICAKQTogQm9hcmQgZ3JvdXBzLCBnYXRld2F5cywgYW5kIG1hcmtldHBsYWNlIHNraWxscyBsZXQgdXNlcnMgZXhwYW5kIHdpdGhvdXQgbG9zaW5nIG9yZ2FuaXphdGlvbi4KCioqUTogSXMgY29kaW5nIG5lZWRlZD8qKiAgCkE6IE5vLiBNb3N0IGZ1bmN0aW9ucyByZWx5IG9uIHNpbXBsZSBhY3Rpb25zIGFuZCBuYXR1cmFsIGxhbmd1YWdlIGluc3RydWN0aW9ucy4KCioqUTogV2h5IGRvIHBlb3BsZSBsaWtlIHVzaW5nIE1pc3Npb24gQ29udHJvbD8qKiAgCkE6IEl0IG1ha2VzIGF1dG9tYXRpb24gcHJlZGljdGFibGUsIG1hbmFnZWFibGUsIGFuZCBzaWduaWZpY2FudGx5IGVhc2llciB0byBzY2FsZS4KCi0tLQoKIyMgU3VtbWFyeQoKVGhlIE9wZW5DbGF3IE1pc3Npb24gQ29udHJvbCBTeXN0ZW0gcmVwcmVzZW50cyBhIHNoaWZ0IGluIGhvdyBwZW9wbGUgdGhpbmsgYWJvdXQgYXV0b21hdGlvbi4gSW5zdGVhZCBvZiBkaXNjb25uZWN0ZWQgdGFza3MgYW5kIHNjYXR0ZXJlZCBtZXNzYWdlcywgdXNlcnMgZ2V0IGEgY29vcmRpbmF0ZWQgc3lzdGVtIHdpdGg6CgotIOKchSBWaXN1YWwgZGFzaGJvYXJkIGZvciBjb21wbGV0ZSBvdmVyc2lnaHQKLSDinIUgU3RydWN0dXJlZCB3b3JrZmxvdyBtYW5hZ2VtZW50Ci0g4pyFIFJlYWwtdGltZSBhY3Rpdml0eSBtb25pdG9yaW5nCi0g4pyFIFNjYWxhYmxlIGFyY2hpdGVjdHVyZQotIOKchSBOby1jb2RlIGF1dG9tYXRpb24KLSDinIUgU2FmZXR5IHRocm91Z2ggYXBwcm92YWwgbGF5ZXJzCgoqKkJvdHRvbSBMaW5lOioqIE1pc3Npb24gQ29udHJvbCBjb252ZXJ0cyBhdXRvbWF0aW9uIGZyb20gYSBidXJkZW4gaW50byBhbiBhZHZhbnRhZ2UsIGdpdmluZyB1c2VycyBhIGZvdW5kYXRpb24gdGhhdCByZW1vdmVzIGZyaWN0aW9uIGFuZCBjcmVhdGVzIHNwYWNlIGZvciBiaWdnZXIgZ29hbHMuCgotLS0KCipDb21waWxlZCBmcm9tIFggYXJ0aWNsZSBieSBKdWxpYW4gR29sZGllIFNFTyogIAoqRW5nYWdlbWVudDogMSByZXBvc3QsIDQgbGlrZXMsIDIgYm9va21hcmtzLCA2MzEgdmlld3MgKGF0IHRpbWUgb2YgY2FwdHVyZSkqCg==", + "uploadedAt": "2026-02-22T04:34:14Z" + } + ] + }, + { + "id": "66f1146e-41c4-4b03-a292-9358b7f9bedb", + "title": "Gantt Board update search ", + "description": "search should be shown as another view, not filtering or showing in the kanban. it should be list of tasks showing no matter what the state", + "type": "task", + "status": "done", + "priority": "urgent", + "project_id": "a1b2c3d4-0001-0000-0000-000000000001", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-21 22:07:19.922+00", + "updated_at": "2026-02-22 17:56:47.524713+00", + "created_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "updated_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [], + "tags": [], + "attachments": [] + }, + { + "id": "56ae2be4-fcf1-403a-87fb-ea9de966f456", + "title": "Mission Control Search Enhancement", + "description": "Implemented comprehensive search feature for Mission Control that searches across all database entities.\n\n**Search Types:**\n- Tasks - with status icon, priority, project name\n- Projects - with color indicator\n- Sprints - with goal/description\n- Documents - with folder name and colored tags\n\n**Features:**\n- Type-based grouped results with counts\n- Real-time debounced search (150ms)\n- Tag colors for documents (infrastructure, monitoring, security, urgent, guide)\n- Extensible architecture via searchConfigs array\n\n**API:** `/api/search?q=query` returns typed results\n\n**Files:**\n- `/app/api/search/route.ts` - Search API with extensible config\n- `/components/layout/quick-search.tsx` - Updated search UI\n\n**To extend:** Add new search types to `searchConfigs` array", + "type": "task", + "status": "done", + "priority": "high", + "project_id": "a1b2c3d4-0001-0000-0000-000000000001", + "sprint_id": null, + "created_at": "2026-02-23 18:53:21.571024+00", + "updated_at": "2026-02-23 19:14:22.369239+00", + "created_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "updated_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [], + "tags": [ + "mission-control", + "search", + "enhancement", + "completed" + ], + "attachments": [] + }, + { + "id": "5d74a680-59a6-4c5a-b07d-2a7b2bdee893", + "title": "Phase 8: Projects overview page", + "description": null, + "type": "task", + "status": "done", + "priority": "medium", + "project_id": "a1b2c3d4-0001-0000-0000-000000000001", + "sprint_id": "b2c3d4e5-0002-0000-0000-000000000002", + "created_at": "2026-02-22 02:57:36+00", + "updated_at": "2026-02-23 20:10:54.842043+00", + "created_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "updated_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [], + "tags": [], + "attachments": [] + }, + { + "id": "65bc8c5a-212a-4532-a027-ea424e62900e", + "title": "Phase 4: Calendar integration", + "description": null, + "type": "task", + "status": "done", + "priority": "medium", + "project_id": "a1b2c3d4-0001-0000-0000-000000000001", + "sprint_id": "b2c3d4e5-0002-0000-0000-000000000002", + "created_at": "2026-02-22 02:57:35+00", + "updated_at": "2026-02-23 20:11:47.757906+00", + "created_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "updated_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [], + "tags": [], + "attachments": [] + }, + { + "id": "f401df02-c072-41b9-b28c-8b71b66da860", + "title": "Implement Ramya's OpenClaw Memory Optimizations", + "description": null, + "type": "task", + "status": "done", + "priority": "urgent", + "project_id": "a1b2c3d4-0002-0000-0000-000000000002", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-22 22:43:32.197289+00", + "updated_at": "2026-02-23 17:32:37.161105+00", + "created_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "updated_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [], + "tags": [ + "openclaw", + "memory", + "optimization", + "performance", + "agent" + ], + "attachments": [] + }, + { + "id": "b9cdfa11-fbb4-4485-8c13-cddc1e39c4fe", + "title": "Review X thread and document insights", + "description": "Review X thread from @hasantoxr and create markdown summary\n\nURL: https://x.com/hasantoxr/status/2025202192073064837?s=46\n\nRead the entire thread, extract key insights, and create a well-formatted markdown file with:\n- Main points\n- Key takeaways\n- Any actionable items or ideas\n- Attach the markdown file to this task\n\nNote: Browser/web search currently unavailable - fetch manually or wait for API fix", + "type": "research", + "status": "done", + "priority": "medium", + "project_id": "a1b2c3d4-0001-0000-0000-000000000001", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-22 03:36:02+00", + "updated_at": "2026-02-23 17:32:37.589204+00", + "created_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "updated_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [], + "tags": [], + "attachments": [ + { + "id": "4066708a-a520-42dc-80a9-b678874b2d91", + "name": "ui-bakery-thread-summary.md", + "size": 3980, + "type": "text/markdown", + "dataUrl": "data:text/markdown;base64,IyBVSSBCYWtlcnk6IFRoZSBFbmQgb2YgJDUwSyBJbnRlcm5hbCBEYXNoYm9hcmRzPwoKKipTb3VyY2U6KiogWCBUaHJlYWQgYnkgW0BoYXNhbnRveHJdKGh0dHBzOi8veC5jb20vaGFzYW50b3hyKSAgCioqRGF0ZToqKiBGZWJydWFyeSAyMSwgMjAyNiAgCioqVVJMOioqIGh0dHBzOi8veC5jb20vaGFzYW50b3hyL3N0YXR1cy8yMDI1MjAyMTkyMDczMDY0ODM3CgotLS0KCiMjIE92ZXJ2aWV3CgpIYXNhbiBUb29yIHNoYXJlcyBhbiBpbi1kZXB0aCBsb29rIGF0ICoqVUkgQmFrZXJ5KiosIGEgbG93LWNvZGUgcGxhdGZvcm0gdGhhdCBnZW5lcmF0ZXMgZnVsbHkgZnVuY3Rpb25hbCBpbnRlcm5hbCBhcHBzIGluIDIgbWludXRlcyB1c2luZyBBSS4gVGhlIHRocmVhZCBwb3NpdGlvbnMgaXQgYXMgYSBwb3RlbnRpYWwgZGlzcnVwdG9yIHRvIHRyYWRpdGlvbmFsIGludGVybmFsIHRvb2wgZGV2ZWxvcG1lbnQgdGhhdCBvZnRlbiBjb3N0cyAkNTBLKyBhbmQgdGFrZXMgbW9udGhzLgoKLS0tCgojIyBNYWluIFBvc3QgKFRoZSBIb29rKQoKPiAiUklQIHRvIGV2ZXJ5IGRldiB0ZWFtIGNoYXJnaW5nICQ1MEsgdG8gYnVpbGQgYW4gaW50ZXJuYWwgZGFzaGJvYXJkLiBVSSBCYWtlcnkganVzdCBtYWRlIGV2ZXJ5IGludGVybmFsIHRvb2wgeW91ciBkZXYgdGVhbSBldmVyIGJ1aWx0IGxvb2sgbGlrZSBhIHdhc3RlIG9mIHRpbWUuIEl0J3MgY2FsbGVkIFVJIEJha2VyeSwgaXQgYnVpbGRzIGFuZCBkZXBsb3lzIGEgZnVsbHkgZnVuY3Rpb25hbCBpbnRlcm5hbCBhcHAgaW4gMiBtaW51dGVzLiBObyBzcHJpbnQuIE5vIEppcmEgdGlja2V0LiBObyBlbmdpbmVlciBib3R0bGVuZWNrLiIKCioqRW5nYWdlbWVudDoqKiAzNSByZXBsaWVzLCA5NCByZXBvc3RzLCAzMzEgbGlrZXMsIDUxMCBib29rbWFya3MsIDY4LjZLIHZpZXdzCgotLS0KCiMjIFdoYXQgVUkgQmFrZXJ5IEFjdHVhbGx5IERvZXMKClRoZSBwbGF0Zm9ybSBlbmFibGVzIHVzZXJzIHRvOgoKMS4gKipDb25uZWN0IHRvIDQ1KyBkYXRhYmFzZXMqKiBpbmNsdWRpbmc6CiAgIC0gUG9zdGdyZXMsIE15U1FMLCBNb25nb0RCCiAgIC0gU25vd2ZsYWtlLCBSZWRpcwogICAtIE9wZW5BSSBpbnRlZ3JhdGlvbgoKMi4gKipEZXNjcmliZSB0aGUgYXBwIGluIHBsYWluIGxhbmd1YWdlKiogLSBOYXR1cmFsIGxhbmd1YWdlIGlucHV0CgozLiAqKkFJIEFnZW50IGdlbmVyYXRlcyBhbmQgZGVwbG95cyoqIC0gRnVsbHkgZnVuY3Rpb25hbCBhcHAgaW4gMiBtaW51dGVzCgo0LiAqKlByb2R1Y3Rpb24tcmVhZHkgb3V0cHV0KiogLSBOb3QgYSBwcm90b3R5cGUsIGJ1dCBhIHJlYWwgYXBwIG9uIGxpdmUgZGF0YSB3aXRoIFNPQyAyIGNvbXBsaWFuY2UKCi0tLQoKIyMgS2V5IEZlYXR1cmVzCgp8IEZlYXR1cmUgfCBEZXNjcmlwdGlvbiB8CnwtLS0tLS0tLS18LS0tLS0tLS0tLS0tLXwKfCAqKjgwKyBQcmUtYnVpbHQgUmVhY3QgQ29tcG9uZW50cyoqIHwgVXNlIGFueXRoaW5nLCBubyByZXN0cmljdGlvbnMgfAp8ICoqT25lLWNsaWNrIERlcGxveSoqIHwgQXV0by1zY2FsaW5nLCBTU0wsIENETiBpbmNsdWRlZCB8CnwgKipFbnRlcnByaXNlIFNlY3VyaXR5KiogfCBCdWlsdC1pbiBSQkFDLCBhdWRpdCBsb2dzLCBNRkEgb3V0IG9mIHRoZSBib3ggfAp8ICoqU2VsZi1ob3N0IE9wdGlvbioqIHwgRm9yIGFpci1nYXBwZWQgZW52aXJvbm1lbnRzIHwKfCAqKlJlYWN0LWJhc2VkKiogfCBNb2Rlcm4sIGV4dGVuc2libGUgc3RhY2sgfAoKLS0tCgojIyBSZWFsLVdvcmxkIFVzZSBDYXNlcwoKVGVhbXMgYXJlIHJlcG9ydGVkbHkgYnVpbGRpbmc6CgotICoqSW52ZW50b3J5IG1hbmFnZW1lbnQqKiBvbiBsaXZlIGRhdGFiYXNlcwotICoqSW52b2ljZSBhcHByb3ZhbCB3b3JrZmxvd3MqKgotICoqQ3VzdG9tZXIgcG9ydGFscyoqCi0gKipBZG1pbiBwYW5lbHMqKiB3aXRoIHJvbGUtYmFzZWQgYWNjZXNzCi0gKipEaWdpdGFsIG1hcmtldGluZyBkYXNoYm9hcmRzKioKCkFsbCBjb25uZWN0ZWQgdG8gcmVhbCBkYXRhIGFuZCBzaGlwcGVkIGluIG1pbnV0ZXMuCgotLS0KCiMjIFNvY2lhbCBQcm9vZiAmIFRyYWN0aW9uCgotICoqNTUsMDAwKyBHaXRIdWIgc3RhcnMqKiBhY3Jvc3Mgb3Blbi1zb3VyY2UgcmVwb3MKLSAqKjQuNy81IHJhdGluZyoqIG9uIEcyCi0gKipQcm9kdWN0IEh1bnQgIzEgUHJvZHVjdCBvZiB0aGUgRGF5KioKLSAqKlRob3VzYW5kcyBvZiBjb21wYW5pZXMqKiB1c2luZyBpdCB3b3JsZHdpZGUKCi0tLQoKIyMgUHJpY2luZwoKLSAqKkZyZWUgdG8gc3RhcnQqKiAtIE5vIGNyZWRpdCBjYXJkIHJlcXVpcmVkCi0gV2Vic2l0ZTogW3VpYmFrZXJ5LmlvXShodHRwczovL3VpYmFrZXJ5LmlvKQoKLS0tCgojIyBLZXkgVGFrZWF3YXlzCgojIyMgRm9yIEJ1c2luZXNzIExlYWRlcnM6Ci0gUG90ZW50aWFsIGRyYW1hdGljIHJlZHVjdGlvbiBpbiBpbnRlcm5hbCB0b29sIGRldmVsb3BtZW50IGNvc3RzCi0gRmFzdGVyIHRpbWUtdG8tbWFya2V0IGZvciBvcGVyYXRpb25hbCBkYXNoYm9hcmRzCi0gUmVkdWNlZCBkZXBlbmRlbmN5IG9uIGVuZ2luZWVyaW5nIHRlYW1zIGZvciBpbnRlcm5hbCB0b29saW5nCgojIyMgRm9yIERldmVsb3BlcnM6Ci0gTWF5IHNoaWZ0IGZvY3VzIGZyb20gYnVpbGRpbmcgaW50ZXJuYWwgdG9vbHMgdG8gaW50ZWdyYXRpbmcvZXh0ZW5kaW5nIHRoZW0KLSBDb3VsZCByZWR1Y2UgInRpY2tldC1kcml2ZW4iIGludGVybmFsIHRvb2wgd29yawotIFJlYWN0LWJhc2VkIGFyY2hpdGVjdHVyZSBzdWdnZXN0cyBleHRlbnNpYmlsaXR5IGZvciB0ZWNobmljYWwgdXNlcnMKCiMjIyBGb3IgdGhlIEluZHVzdHJ5OgotIFBhcnQgb2YgdGhlIGJyb2FkZXIgdHJlbmQgb2YgQUktcG93ZXJlZCBhcHAgZ2VuZXJhdGlvbgotIFN1Z2dlc3RzIGNvbW1vZGl0aXphdGlvbiBvZiBiYXNpYyBDUlVEL2ludGVybmFsIGRhc2hib2FyZCBkZXZlbG9wbWVudAotIE1heSBmb3JjZSByZXRoaW5raW5nIG9mIGhvdyBpbnRlcm5hbCB0b29saW5nIGJ1ZGdldHMgYXJlIGFsbG9jYXRlZAoKLS0tCgojIyBDcml0aWNhbCBRdWVzdGlvbnMgdG8gQ29uc2lkZXIKCjEuICoqVmVuZG9yIExvY2staW46KiogSG93IHBvcnRhYmxlIGFyZSBhcHBzIGJ1aWx0IHdpdGggVUkgQmFrZXJ5PwoyLiAqKkNvbXBsZXhpdHkgQ2VpbGluZzoqKiBXaGVyZSBkb2VzIGl0IGJyZWFrIGRvd24gZm9yIHNvcGhpc3RpY2F0ZWQgdXNlIGNhc2VzPwozLiAqKkVudGVycHJpc2UgSW50ZWdyYXRpb246KiogSG93IHdlbGwgZG9lcyBpdCBwbGF5IHdpdGggZXhpc3RpbmcgZW50ZXJwcmlzZSBzeXN0ZW1zPwo0LiAqKkxvbmctdGVybSBWaWFiaWxpdHk6KiogSXMgdGhlIHByaWNpbmcgc3VzdGFpbmFibGUgYXMgYWRvcHRpb24gc2NhbGVzPwoKLS0tCgojIyBSZWxhdGVkIFRvb2xzICYgRWNvc3lzdGVtCgpUaGlzIGZpdHMgaW50byB0aGUgYnJvYWRlciBjYXRlZ29yeSBvZjoKLSAqKkxvdy1jb2RlL05vLWNvZGUgcGxhdGZvcm1zKiogKFJldG9vbCwgQXBwc21pdGgsIEJ1ZGliYXNlKQotICoqQUkgYXBwIGdlbmVyYXRvcnMqKiAodjAsIEJvbHQsIFJlcGxpdCBBZ2VudCkKLSAqKkludGVybmFsIHRvb2wgYnVpbGRlcnMqKiAoVG9vbEpldCwgUmVmaW5lKQoKLS0tCgojIyBBY3Rpb24gSXRlbXMgKElmIEV4cGxvcmluZykKCi0gWyBdIFNpZ24gdXAgZm9yIGZyZWUgdGllciBhdCB1aWJha2VyeS5pbwotIFsgXSBUZXN0IHdpdGggYSBzaW1wbGUgQ1JVRCB1c2UgY2FzZQotIFsgXSBFdmFsdWF0ZSBkYXRhIHNvdXJjZSBjb25uZWN0b3JzIGZvciB5b3VyIHN0YWNrCi0gWyBdIENvbXBhcmUgYWdhaW5zdCBjdXJyZW50IGludGVybmFsIHRvb2wgZGV2ZWxvcG1lbnQgY29zdHMKLSBbIF0gQXNzZXNzIHNlY3VyaXR5L2NvbXBsaWFuY2UgcmVxdWlyZW1lbnRzIGZvciB5b3VyIG9yZwoKLS0tCgoqVGhyZWFkIGNvbXBpbGVkIGZyb20gWCBwb3N0IGJ5IEBoYXNhbnRveHIuIEVuZ2FnZW1lbnQgbWV0cmljcyBjYXB0dXJlZCBhdCB0aW1lIG9mIHJlYWRpbmcuKgo=", + "uploadedAt": "2026-02-22T03:44:08Z" + } + ] + }, + { + "id": "715a44e9-aaa4-43b5-a940-1e57125d943f", + "title": "Review X thread - OpenClaw Context Management Guide by Johann Sath", + "description": "Critical guide on managing OpenClaw context limits\n\nSource: @johann_sath\nURL: https://x.com/johann_sath/status/2025440759416045702\n\nKey strategies covered:\n1. Orchestrator pattern in SOUL.md\n2. BRAIN.md as external memory\n3. Efficient heartbeats (<3s)\n4. Isolated cron jobs\n5. Subagent delegation\n\nResult: Keep main session under 30K context (vs 150K limit)\n\nFull implementation guide attached.", + "type": "research", + "status": "done", + "priority": "high", + "project_id": "a1b2c3d4-0001-0000-0000-000000000001", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-22 07:05:38+00", + "updated_at": "2026-02-23 17:32:37.732829+00", + "created_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "updated_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [], + "tags": [ + "openclaw", + "optimization", + "context-management" + ], + "attachments": [ + { + "id": "6acbd910-b11e-46e4-88f9-cd5dd16bbfa8", + "name": "openclaw-context-management-guide.md", + "size": 2863, + "type": "text/markdown", + "dataUrl": "data:text/markdown;base64,IyBIb3cgdG8gTmV2ZXIgSGl0IE9wZW5DbGF3J3MgMTUwSyBDb250ZXh0IExpbWl0CgoqKlNvdXJjZToqKiBYIFRocmVhZCBieSBbSm9oYW5uIFNhdGhpYW5hdGhlbl0oaHR0cHM6Ly94LmNvbS9qb2hhbm5fc2F0aCkgIAoqKkRhdGU6KiogRmVicnVhcnkgMjEsIDIwMjYgIAoqKlVSTDoqKiBodHRwczovL3guY29tL2pvaGFubl9zYXRoL3N0YXR1cy8yMDI1NDQwNzU5NDE2MDQ1NzAyCgotLS0KCiMjIFRoZSBQcm9ibGVtCgpNb3N0IE9wZW5DbGF3IHVzZXJzIGhpdCAxNTBLIGNvbnRleHQgaW4gYSBzaW5nbGUgY29udmVyc2F0aW9uIGFuZCB3b25kZXIgd2h5IHRoZWlyIGFnZW50IGdldHMgZHVtYmVyLiBUaGUgc29sdXRpb24gaXNuJ3QgYSBiaWdnZXIgd2luZG934oCUaXQncyBuZXZlciBuZWVkaW5nIG9uZS4KCi0tLQoKIyMgVGhlIDUgU3RyYXRlZ2llcwoKIyMjIDEuIEFkZCAiT3JjaGVzdHJhdG9yIiBQYXR0ZXJuIHRvIFNPVUwubWQKCioqRmlsZToqKiBgU09VTC5tZGAgIAoqKkFkZDoqKiAiWW91IGFyZSB0aGUgb3JjaGVzdHJhdG9yLiBTdWJhZ2VudHMgZXhlY3V0ZS4iCgoqKldoeSBpdCB3b3JrczoqKgotIE1haW4gc2Vzc2lvbiBzdGF5cyBsZWFuCi0gSGVhdnkgd29yayBydW5zIGluIGZyZXNoIGNvbnRleHQgd2luZG93cwotIFN1YmFnZW50cyBzcGF3biwgd29yaywgcmVwb3J0IGJhY2ssIGNvbnRleHQgZGllcwoKKipSZXN1bHQ6KiogTWFpbiBzZXNzaW9uIHJ1bnMgMjQvNyB3aXRob3V0IGJsb2F0CgotLS0KCiMjIyAyLiBVc2UgQlJBSU4ubWQgYXMgRXh0ZXJuYWwgTWVtb3J5CgoqKkZpbGU6KiogYEJSQUlOLm1kYCAgCioqUGF0dGVybjoqKiBBZ2VudCByZWFkcyAmIHdyaXRlcyBpbnN0ZWFkIG9mIHJlbWVtYmVyaW5nIGV2ZXJ5dGhpbmcgaW4tY29udGV4dAoKKipXaHkgaXQgd29ya3M6KioKLSBPZmZsb2FkcyBtZW1vcnkgZnJvbSBjb250ZXh0IHRvIGRpc2sKLSBBZ2VudCByZWZlcmVuY2VzIGZpbGVzIGluc3RlYWQgb2YgcmVjYWxsaW5nCi0gU3RydWN0dXJlZCBzdG9yYWdlIGZvciBjb21wbGV4IHN0YXRlCgotLS0KCiMjIyAzLiBTZXQgVXAgSGVhcnRiZWF0cwoKKipQYXR0ZXJuOioqIEZhc3QgY2hlY2staW5zICg8M3MpIHRoYXQgZG9uJ3QgbG9hZCBmaWxlcyB1bmxlc3MgeW91J3JlIGlkbGUKCioqSW1wbGVtZW50YXRpb246KioKLSBPbmx5IGNoZWNrIGNyaXRpY2FsIGl0ZW1zCi0gU2tpcCBmaWxlIHJlYWRzIHVubGVzcyBuZWNlc3NhcnkKLSBCYXRjaCBtdWx0aXBsZSBjaGVja3MgdG9nZXRoZXIKCioqQmVuZWZpdDoqKiBLZWVwcyBzZXNzaW9uIHJlc3BvbnNpdmUgd2l0aG91dCBjb250ZXh0IGJsb2F0CgotLS0KCiMjIyA0LiBSdW4gQ3JvbiBKb2JzIElzb2xhdGVkCgoqKlBhdHRlcm46KiogRWFjaCBjcm9uIGpvYiBnZXRzIGl0cyBvd24gc2Vzc2lvbgoKKipXaHkgaXQgd29ya3M6KioKLSBOZXZlciBibG9hdHMgbWFpbiB0aHJlYWQKLSBJbmRlcGVuZGVudCBleGVjdXRpb24gY29udGV4dHMKLSBQYXJhbGxlbCBwcm9jZXNzaW5nIHdpdGhvdXQgaW50ZXJmZXJlbmNlCgotLS0KCiMjIyA1LiBEZWxlZ2F0ZSBFdmVyeXRoaW5nIHRvIFN1YmFnZW50cwoKKipQYXR0ZXJuOioqIFN1YmFnZW50IHNwYXducyDihpIgZG9lcyB3b3JrIOKGkiByZXBvcnRzIGJhY2sg4oaSIGNvbnRleHQgZGllcwoKKipGbG93OioqCjEuIE1haW4gc2Vzc2lvbiBpZGVudGlmaWVzIHRhc2sKMi4gU3Bhd25zIHN1YmFnZW50IHdpdGggc3BlY2lmaWMgZ29hbAozLiBTdWJhZ2VudCBjb21wbGV0ZXMgd29yayBpbiBpc29sYXRpb24KNC4gUmVwb3J0cyByZXN1bHRzIGJhY2sKNS4gU3ViYWdlbnQgY29udGV4dCBnYXJiYWdlIGNvbGxlY3RlZAoKLS0tCgojIyBUaGUgUmVzdWx0CgpKb2hhbm4ncyBtYWluIHNlc3Npb246Ci0gUnVucyAyNC83Ci0gKipSYXJlbHkgcGFzc2VzIDMwSyBjb250ZXh0KioKLSBTdGF5cyByZXNwb25zaXZlIGFuZCBzbWFydAoKKipLZXkgaW5zaWdodDoqKiBUaGUgdHJpY2sgaXNuJ3QgYSBiaWdnZXIgd2luZG93LiBJdCdzIG5ldmVyIG5lZWRpbmcgb25lLgoKLS0tCgojIyBJbXBsZW1lbnRhdGlvbiBDaGVja2xpc3QKCi0gWyBdIEFkZCBvcmNoZXN0cmF0b3IgcGF0dGVybiB0byBTT1VMLm1kCi0gWyBdIENyZWF0ZS9pbXByb3ZlIEJSQUlOLm1kIGZvciBleHRlcm5hbCBtZW1vcnkKLSBbIF0gQXVkaXQgaGVhcnRiZWF0cyBmb3IgZWZmaWNpZW5jeSAoPDNzIGNoZWNrcykKLSBbIF0gUmV2aWV3IGNyb24gam9icyBmb3IgaXNvbGF0aW9uCi0gWyBdIElkZW50aWZ5IG9wcG9ydHVuaXRpZXMgZm9yIHN1YmFnZW50IGRlbGVnYXRpb24KCi0tLQoKIyMgUmVsYXRlZCBSZXNvdXJjZXMKCi0gKipTT1VMLm1kIEd1aWRlOioqIGh0dHBzOi8vc291bC5tZCAoZGVmaW5pbmcgQUkgaWRlbnRpdHkpCi0gKipKb2hhbm4ncyBXZWVrbHkgTmV3c2xldHRlcjoqKiBodHRwczovL2pvaGFubi5meWkKLSAqKkF1dGhvcjoqKiBCdWlsZGluZyBkbXByby5haSAoZXgtQ2lzY28pLCAxeCBleGl0LCBmb3VuZGVyIEBqYXJzX2dsb2JhbAoKLS0tCgojIyBLZXkgVGFrZWF3YXkKCkNvbnRleHQgbWFuYWdlbWVudCBpc24ndCBhYm91dCBoYXZpbmcgbW9yZeKAlGl0J3MgYWJvdXQgdXNpbmcgbGVzcyBieToKMS4gT3JjaGVzdHJhdGluZyBpbnN0ZWFkIG9mIGV4ZWN1dGluZwoyLiBFeHRlcm5hbGl6aW5nIG1lbW9yeQozLiBFZmZpY2llbnQgcG9sbGluZwo0LiBJc29sYXRlZCBzY2hlZHVsaW5nCjUuIERlbGVnYXRpbmcgdG8gc3ViYWdlbnRzCgotLS0KCipDb21waWxlZCBmcm9tIFggdGhyZWFkIGJ5IEpvaGFubiBTYXRoaWFuYXRoZW4qICAKKkVuZ2FnZW1lbnQ6IDUgcmVwbGllcywgNSByZXBvc3RzLCA2MCBsaWtlcywgMTk5IGJvb2ttYXJrcywgNSwxOTggdmlld3MqCg==", + "uploadedAt": "2026-02-22T07:05:45Z" + } + ] + }, + { + "id": "57bc2efe-eb60-4cc7-a8b2-59d7bf8dc736", + "title": "Phase 3: Enhance Mission page with real progress", + "description": null, + "type": "task", + "status": "done", + "priority": "medium", + "project_id": "a1b2c3d4-0001-0000-0000-000000000001", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-22 02:57:35+00", + "updated_at": "2026-02-23 17:32:36.816106+00", + "created_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "updated_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [ + { + "id": "c-start", + "text": "Subagent spawned for Mission page progress enhancements", + "commentAuthorId": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "replies": [], + "createdAt": "2026-02-22T05:02:39.074Z" + } + ], + "tags": [], + "attachments": [] + }, + { + "id": "d9905880-1b03-49e2-8f81-bf0362055571", + "title": "Build Project Screen in Gantt Board", + "description": "**Goal:** Create a comprehensive Project management screen in Gantt Board similar to the Sprints page.\n\n**Requirements:**\n\n**1. Projects List Page (`/projects`)**\n- Grid/list view of all projects\n- Show project name, color, description, task count\n- Click to navigate to project detail\n- Create new project button\n\n**2. Project Detail Page (`/projects/[id]`)**\n- Project header with name, color, description (editable)\n- CRUD operations (Create, Read, Update, Delete)\n- List of tasks in the project\n- Drag & drop to reorder tasks\n- Move tasks between projects\n\n**3. No Project / Backlog Area**\n- Area for tasks without a project assigned\n- Drag tasks from here to assign to a project\n- Drag tasks to here to unassign\n\n**4. Navigation Integration**\n- Update Mission Control project links to go to `/projects/[id]`\n- URL param `?project=xxx` should redirect to project page\n\n**5. UI Components Needed:**\n- ProjectCard - for list view\n- ProjectDetail - for detail page\n- ProjectTaskBoard - kanban view of project tasks\n- UnassignedTasksPanel - backlog area\n\n**Reference:** See Sprints page implementation for patterns\n\n**Files to Create:**\n- `/app/projects/page.tsx` - List view\n- `/app/projects/[id]/page.tsx` - Detail view\n- `/components/ProjectCard.tsx`\n- `/components/ProjectTaskBoard.tsx`\n- `/components/UnassignedTasksPanel.tsx`\n\n**Acceptance Criteria:**\n- [ ] Can view all projects in list/grid\n- [ ] Can create new project\n- [ ] Can edit project details\n- [ ] Can delete project\n- [ ] Can view tasks in a project\n- [ ] Can drag/drop tasks between projects\n- [ ] Can move tasks to/from unassigned\n- [ ] Mission Control project clicks navigate correctly", + "type": "task", + "status": "in-progress", + "priority": "high", + "project_id": "a1b2c3d4-0002-0000-0000-000000000002", + "sprint_id": "b2c3d4e5-0002-0000-0000-000000000002", + "created_at": "2026-02-23 19:35:53.314297+00", + "updated_at": "2026-02-23 19:48:10.210403+00", + "created_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "updated_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [ + { + "id": "c-start", + "text": "[2026-02-23 13:45] Subagent spawned to build Project Screen. Status changed to in-progress.", + "commentAuthorId": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "replies": [], + "createdAt": "2026-02-23T13:45:00Z" + } + ], + "tags": [ + "gantt-board", + "projects", + "feature", + "ui" + ], + "attachments": [] + }, + { + "id": "4b81b11d-2348-44aa-9bf6-b00ba075ac4a", + "title": "BUG: Mission Control Search Not Returning Results", + "description": "**Bug Description:**\nMission Control search is not working properly. When searching for keywords like \"mission\" or \"openclaw\", the search returns empty results or incomplete data.\n\n**Current Search Implementation:**\n\n**File:** `/app/api/search/route.ts`\n\n**Currently Searched Tables:**\n1. **tasks** - Fields: title, description\n2. **projects** - Fields: name, description \n3. **sprints** - Fields: name, goal\n4. **mission_control_documents** - Fields: title, content\n\n**Current Logic:**\n- Uses Supabase `.or()` with `ilike` filters\n- Searches each table independently\n- Results grouped by type\n- Limit 10 results per table, 50 total\n\n**Expected Behavior:**\nSearch should return results from ALL tables that contain the search term in any searchable field.\n\n**Actual Behavior:**\n- Documents not appearing in search results\n- Some queries return empty when they should have matches\n\n**Acceptance Criteria:**\n- [ ] Search returns tasks matching title/description\n- [ ] Search returns projects matching name/description\n- [ ] Search returns sprints matching name/goal\n- [ ] Search returns documents matching title/content\n- [ ] Results properly grouped by type with counts\n- [ ] Clicking result navigates to correct page\n\n**Testing:**\nQuery: `?q=mission` should return:\n- Tasks with \"mission\" in title/description\n- Projects with \"mission\" in name/description\n- Documents with \"mission\" in title/content", + "type": "bug", + "status": "review", + "priority": "high", + "project_id": "a1b2c3d4-0001-0000-0000-000000000001", + "sprint_id": "b2c3d4e5-0002-0000-0000-000000000002", + "created_at": "2026-02-23 19:35:23.74919+00", + "updated_at": "2026-02-23 20:31:39.083735+00", + "created_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "updated_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [ + { + "id": "c-start", + "text": "[2026-02-23 13:45] Subagent spawned to work on this bug. Status changed to in-progress.", + "commentAuthorId": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "replies": [], + "createdAt": "2026-02-23T13:45:00Z" + } + ], + "tags": [ + "mission-control", + "search", + "bug", + "api" + ], + "attachments": [] + }, + { + "id": "ce4a73a0-713c-4707-ae96-69dc40199ea5", + "title": "Digital podcast from daily digest.", + "description": null, + "type": "research", + "status": "in-progress", + "priority": "high", + "project_id": "a1b2c3d4-0001-0000-0000-000000000001", + "sprint_id": "b2c3d4e5-0002-0000-0000-000000000002", + "created_at": "2026-02-22 06:55:42.323+00", + "updated_at": "2026-02-23 19:48:26.885792+00", + "created_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "updated_by_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [ + { + "id": "c-status", + "text": "[2026-02-23 13:45] This task has been sitting in-progress but no work has been done. Research on TTS (text-to-speech) for converting daily digest to podcast format is still needed. Need to research: 1) TTS providers (ElevenLabs, OpenAI, etc.), 2) Audio hosting options, 3) RSS feed generation for podcast distribution. Will pick up when higher priority tasks are complete.", + "commentAuthorId": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "replies": [], + "createdAt": "2026-02-23T13:45:00Z" + } + ], + "tags": [ + "research", + "blog" + ], + "attachments": [] + }, + { + "id": "e326dcb6-c096-4845-8f5b-8aaf9ed1d40e", + "title": "Fix monitoring schedule - 2 of 3 sites are down", + "description": "The cron job running every 10 minutes to check heartbeat website is failing.", + "type": "bug", + "status": "done", + "priority": "urgent", + "project_id": "a1b2c3d4-0002-0000-0000-000000000002", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-18 17:01:23.109+00", + "updated_at": "2026-02-21 17:41:53.330535+00", + "created_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "updated_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [ + { + "id": "c16", + "text": "FIXED: Updated cron job with pkill cleanup before restart + 2s delay. Created backup script: monitor-restart.sh", + "commentAuthorId": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "replies": [], + "createdAt": "2026-02-18T17:01:23.109Z" + } + ], + "tags": [ + "monitoring", + "cron", + "bug", + "infrastructure", + "urgent", + "Web Projects" + ], + "attachments": [] + }, + { + "id": "7da72025-4216-4bb8-ad98-a8cb1b89d687", + "title": "Investigate root cause - why are websites dying?", + "description": "Currently monitoring only treats the symptom (restart when down). Need to investigate what is actually killing the Next.js dev servers.", + "type": "research", + "status": "done", + "priority": "high", + "project_id": "a1b2c3d4-0002-0000-0000-000000000002", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-18 17:01:23.109+00", + "updated_at": "2026-02-21 17:41:53.330535+00", + "created_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "updated_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [ + { + "id": "c27", + "text": "COMPLETED: Root cause analysis done. Primary suspect: Next.js dev server memory leaks. Secondary: SSH timeout, OOM killer, power mgmt. Full report: root-cause-analysis.md. Monitoring script deployed.", + "commentAuthorId": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "replies": [], + "createdAt": "2026-02-18T17:01:23.109Z" + } + ], + "tags": [ + "debugging", + "research", + "infrastructure", + "root-cause", + "Web Projects" + ], + "attachments": [] + }, + { + "id": "f526d0b1-6602-464b-aa0e-d1038918fbef", + "title": "Add ability to edit task priority in Kanban board", + "description": "Currently users cannot change task priority (Low/Medium/High/Urgent) from the UI.", + "type": "task", + "status": "done", + "priority": "high", + "project_id": "a1b2c3d4-0002-0000-0000-000000000002", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-18 17:01:23.109+00", + "updated_at": "2026-02-21 17:41:53.330535+00", + "created_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "updated_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [ + { + "id": "c28", + "text": "COMPLETED: Added priority buttons to task detail dialog. Click any task to see Low/Medium/High/Urgent buttons with color coding. Changes apply immediately.", + "commentAuthorId": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "replies": [], + "createdAt": "2026-02-18T17:01:23.109Z" + } + ], + "tags": [ + "ui", + "kanban", + "feature", + "priority", + "Web Projects" + ], + "attachments": [] + }, + { + "id": "96dd0ce8-4ac7-4e1d-9e5f-06648e9304ff", + "title": "Redesign Heartbeat Monitor to match UptimeRobot", + "description": "Completely redesign the Heartbeat Monitor website to be a competitor to https://uptimerobot.com.", + "type": "task", + "status": "done", + "priority": "high", + "project_id": "a1b2c3d4-0002-0000-0000-000000000002", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-18 17:01:23.109+00", + "updated_at": "2026-02-21 17:41:53.330535+00", + "created_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "updated_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [ + { + "id": "c29", + "text": "COMPLETED: Full rebuild with Next.js + shadcn/ui + Framer Motion. Dark OLED theme, glass-morphism cards, animated status indicators, sparkline visualizations, grid/list views, tooltips, progress bars. Production-grade at http://localhost:3005", + "commentAuthorId": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "replies": [], + "createdAt": "2026-02-18T17:01:23.109Z" + } + ], + "tags": [ + "ui", + "ux", + "redesign", + "dashboard", + "monitoring", + "Web Projects" + ], + "attachments": [] + }, + { + "id": "92cdad6c-0f48-4c2e-b306-2a0be0a90703", + "title": "Redesign Gantt Board", + "description": "Make it actually work with proper notes system", + "type": "task", + "status": "archived", + "priority": "high", + "project_id": "a1b2c3d4-0002-0000-0000-000000000002", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-18 17:01:23.109+00", + "updated_at": "2026-02-21 17:41:53.330535+00", + "created_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "updated_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [ + { + "id": "c1", + "text": "Need 1-to-many notes, not one big text field", + "commentAuthorId": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "replies": [], + "createdAt": "2026-02-18T17:01:23.109Z" + }, + { + "id": "c2", + "text": "Agreed - will rebuild with proper comment threads", + "commentAuthorId": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "replies": [], + "createdAt": "2026-02-18T17:01:23.109Z" + } + ], + "tags": [ + "ui", + "rewrite", + "Web Projects" + ], + "attachments": [] + }, + { + "id": "6e78e125-7ced-415a-9705-fd4a82e3ff2f", + "title": "Set up Gitea integration for code pushes", + "description": "Create bot account on Gitea (192.168.1.128:3000) and configure git remotes for all OpenClaw projects.", + "type": "task", + "status": "done", + "priority": "medium", + "project_id": "a1b2c3d4-0002-0000-0000-000000000002", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-18 17:01:23.109+00", + "updated_at": "2026-02-21 17:41:53.330535+00", + "created_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "updated_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [ + { + "id": "c3", + "text": "User has local Gitea at http://192.168.1.128:3000", + "commentAuthorId": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "replies": [], + "createdAt": "2026-02-18T17:01:23.109Z" + }, + { + "id": "c7", + "text": "✅ All 3 repos created and pushed to Gitea: gantt-board, blog-backup, heartbeat-monitor", + "commentAuthorId": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "replies": [], + "createdAt": "2026-02-18T17:01:23.109Z" + } + ], + "tags": [ + "gitea", + "git", + "automation", + "infrastructure", + "Web Projects" + ], + "attachments": [] + }, + { + "id": "0ed2b9b9-787a-4441-a35b-3047cc9c9cf9", + "title": "RESEARCH: Find viable screenshot solution for OpenClaw on macOS", + "description": "INVESTIGATION NEEDED: Find a reliable, persistent way for OpenClaw AI to capture screenshots of local websites running on macOS.", + "type": "research", + "status": "done", + "priority": "high", + "project_id": "a1b2c3d4-0002-0000-0000-000000000002", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-18 17:01:23.109+00", + "updated_at": "2026-02-21 17:41:53.330535+00", + "created_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "updated_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [ + { + "id": "c39", + "text": "SUCCESS: Playwright + Google Chrome works! Successfully captured screenshot of http://localhost:3005 using headless Chrome", + "commentAuthorId": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "replies": [], + "createdAt": "2026-02-18T17:01:23.109Z" + }, + { + "id": "c47", + "text": "COMPLETED: Playwright installed globally. Screenshots now work anytime without setup.", + "commentAuthorId": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "replies": [], + "createdAt": "2026-02-18T17:01:23.109Z" + } + ], + "tags": [ + "research", + "screenshot", + "macos", + "openclaw", + "investigation", + "Web Projects" + ], + "attachments": [] + }, + { + "id": "3b168e8f-d0a0-4341-a382-673d1e42f9de", + "title": "Fix Blog Backup links to be clickable", + "description": "Make links in the Daily Digest clickable in the blog backup UI.", + "type": "task", + "status": "done", + "priority": "medium", + "project_id": "a1b2c3d4-0002-0000-0000-000000000002", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-18 17:01:23.109+00", + "updated_at": "2026-02-21 17:41:53.330535+00", + "created_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "updated_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [ + { + "id": "c41", + "text": "COMPLETED: Fixed parseDigest to extract URLs from markdown links [Title](url) in title lines", + "commentAuthorId": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "replies": [], + "createdAt": "2026-02-18T17:01:23.109Z" + }, + { + "id": "c42", + "text": "COMPLETED: Title is now the clickable link with external link icon on hover", + "commentAuthorId": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "replies": [], + "createdAt": "2026-02-18T17:01:23.109Z" + } + ], + "tags": [ + "blog", + "ui", + "markdown", + "links", + "Web Projects" + ], + "attachments": [] + }, + { + "id": "5782e4a8-60e0-4b1b-87af-6fe0cf0eb1fd", + "title": "Fix Kanban board - dynamic sync without hard refresh", + "description": "Current board uses localStorage persistence which requires hard refresh (Cmd+Shift+R) to see task updates from code changes.", + "type": "task", + "status": "done", + "priority": "medium", + "project_id": "a1b2c3d4-0002-0000-0000-000000000002", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-18 17:01:23.109+00", + "updated_at": "2026-02-21 17:41:53.330535+00", + "created_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "updated_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [ + { + "id": "c44", + "text": "COMPLETED: Added /api/tasks endpoint with file-based storage", + "commentAuthorId": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "replies": [], + "createdAt": "2026-02-18T17:01:23.109Z" + }, + { + "id": "c45", + "text": "COMPLETED: Store now syncs from server on load and auto-syncs changes", + "commentAuthorId": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "replies": [], + "createdAt": "2026-02-18T17:01:23.109Z" + } + ], + "tags": [ + "ui", + "sync", + "localstorage", + "real-time", + "Web Projects" + ], + "attachments": [] + }, + { + "id": "341b7747-9a99-409e-99ea-52dfddacefe7", + "title": "Add markdown rendering to Blog Backup", + "description": "The blog backup page currently shows raw markdown text instead of rendered HTML.", + "type": "task", + "status": "done", + "priority": "high", + "project_id": "a1b2c3d4-0002-0000-0000-000000000002", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-18 17:01:23.109+00", + "updated_at": "2026-02-21 17:41:53.330535+00", + "created_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "updated_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [ + { + "id": "c58", + "text": "COMPLETED: Installed react-markdown and remark-gfm", + "commentAuthorId": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "replies": [], + "createdAt": "2026-02-18T17:01:23.109Z" + }, + { + "id": "c61", + "text": "COMPLETED: Links now open in new tab with blue styling and hover effects", + "commentAuthorId": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "replies": [], + "createdAt": "2026-02-18T17:01:23.109Z" + } + ], + "tags": [ + "blog", + "ui", + "markdown", + "frontend", + "Web Projects" + ], + "attachments": [] + }, + { + "id": "e4a28449-c065-409a-8205-cdec01c910d5", + "title": "Implement daily data backup system", + "description": "Create automated daily backup of all web app data to Git. All 3 apps (gantt-board, blog-backup, heartbeat-monitor) now have data persistence with JSON files in data/ directories. Need daily backup cron job that commits data to Gitea to prevent data loss on server restarts.", + "type": "task", + "status": "done", + "priority": "high", + "project_id": "a1b2c3d4-0002-0000-0000-000000000002", + "sprint_id": "b2c3d4e5-0001-0000-0000-000000000001", + "created_at": "2026-02-19 13:00:00+00", + "updated_at": "2026-02-21 17:41:53.330535+00", + "created_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "updated_by_id": "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9", + "assignee_id": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "due_date": null, + "comments": [ + { + "id": "c66", + "text": "All 3 apps verified to have data/ directories with JSON persistence", + "commentAuthorId": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "replies": [], + "createdAt": "2026-02-19T13:00:00.000Z" + }, + { + "id": "c67", + "text": "Created daily-backup.sh script to commit data to Git", + "commentAuthorId": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "replies": [], + "createdAt": "2026-02-19T13:00:00.000Z" + }, + { + "id": "c68", + "text": "Added cron job for 11:00 PM CST daily backups", + "commentAuthorId": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "replies": [], + "createdAt": "2026-02-19T13:00:00.000Z" + }, + { + "id": "c69", + "text": "Backup logs to memory/backup.log for monitoring", + "commentAuthorId": "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa", + "replies": [], + "createdAt": "2026-02-19T13:00:00.000Z" + } + ], + "tags": [ + "backup", + "infrastructure", + "data-persistence", + "automation", + "Web Projects" + ], + "attachments": [] + } +] \ No newline at end of file diff --git a/supabase/update_task_comments_only.sql b/supabase/update_task_comments_only.sql new file mode 100644 index 0000000..072414f --- /dev/null +++ b/supabase/update_task_comments_only.sql @@ -0,0 +1,22 @@ +-- Updates only tasks.comments using {id, comments} payload. +-- Generated from supabase/tasks.json on 2026-02-23. +BEGIN; + +WITH payload AS ( + SELECT * + FROM jsonb_to_recordset( + $payload$ +[{"id":"57bc2efe-eb60-4cc7-a8b2-59d7bf8dc736","comments":[{"id":"c-start","text":"Subagent spawned for Mission page progress enhancements","createdAt":"2026-02-22T05:02:39.074Z","commentAuthorId":"9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa","replies":[]}]},{"id":"d9905880-1b03-49e2-8f81-bf0362055571","comments":[{"id":"c-start","text":"[2026-02-23 13:45] Subagent spawned to build Project Screen. Status changed to in-progress.","createdAt":"2026-02-23T13:45:00Z","commentAuthorId":"9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa","replies":[]}]},{"id":"4b81b11d-2348-44aa-9bf6-b00ba075ac4a","comments":[{"id":"c-start","text":"[2026-02-23 13:45] Subagent spawned to work on this bug. Status changed to in-progress.","createdAt":"2026-02-23T13:45:00Z","commentAuthorId":"9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa","replies":[]}]},{"id":"ce4a73a0-713c-4707-ae96-69dc40199ea5","comments":[{"id":"c-status","text":"[2026-02-23 13:45] This task has been sitting in-progress but no work has been done. Research on TTS (text-to-speech) for converting daily digest to podcast format is still needed. Need to research: 1) TTS providers (ElevenLabs, OpenAI, etc.), 2) Audio hosting options, 3) RSS feed generation for podcast distribution. Will pick up when higher priority tasks are complete.","createdAt":"2026-02-23T13:45:00Z","commentAuthorId":"9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa","replies":[]}]},{"id":"e326dcb6-c096-4845-8f5b-8aaf9ed1d40e","comments":[{"id":"c16","text":"FIXED: Updated cron job with pkill cleanup before restart + 2s delay. Created backup script: monitor-restart.sh","createdAt":"2026-02-18T17:01:23.109Z","commentAuthorId":"9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa","replies":[]}]},{"id":"7da72025-4216-4bb8-ad98-a8cb1b89d687","comments":[{"id":"c27","text":"COMPLETED: Root cause analysis done. Primary suspect: Next.js dev server memory leaks. Secondary: SSH timeout, OOM killer, power mgmt. Full report: root-cause-analysis.md. Monitoring script deployed.","createdAt":"2026-02-18T17:01:23.109Z","commentAuthorId":"9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa","replies":[]}]},{"id":"f526d0b1-6602-464b-aa0e-d1038918fbef","comments":[{"id":"c28","text":"COMPLETED: Added priority buttons to task detail dialog. Click any task to see Low/Medium/High/Urgent buttons with color coding. Changes apply immediately.","createdAt":"2026-02-18T17:01:23.109Z","commentAuthorId":"9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa","replies":[]}]},{"id":"96dd0ce8-4ac7-4e1d-9e5f-06648e9304ff","comments":[{"id":"c29","text":"COMPLETED: Full rebuild with Next.js + shadcn/ui + Framer Motion. Dark OLED theme, glass-morphism cards, animated status indicators, sparkline visualizations, grid/list views, tooltips, progress bars. Production-grade at http://localhost:3005","createdAt":"2026-02-18T17:01:23.109Z","commentAuthorId":"9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa","replies":[]}]},{"id":"92cdad6c-0f48-4c2e-b306-2a0be0a90703","comments":[{"id":"c1","text":"Need 1-to-many notes, not one big text field","createdAt":"2026-02-18T17:01:23.109Z","commentAuthorId":"9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa","replies":[]},{"id":"c2","text":"Agreed - will rebuild with proper comment threads","createdAt":"2026-02-18T17:01:23.109Z","commentAuthorId":"9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa","replies":[]}]},{"id":"6e78e125-7ced-415a-9705-fd4a82e3ff2f","comments":[{"id":"c3","text":"User has local Gitea at http://192.168.1.128:3000","createdAt":"2026-02-18T17:01:23.109Z","commentAuthorId":"9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa","replies":[]},{"id":"c7","text":"✅ All 3 repos created and pushed to Gitea: gantt-board, blog-backup, heartbeat-monitor","createdAt":"2026-02-18T17:01:23.109Z","commentAuthorId":"9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa","replies":[]}]},{"id":"0ed2b9b9-787a-4441-a35b-3047cc9c9cf9","comments":[{"id":"c39","text":"SUCCESS: Playwright + Google Chrome works! Successfully captured screenshot of http://localhost:3005 using headless Chrome","createdAt":"2026-02-18T17:01:23.109Z","commentAuthorId":"9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa","replies":[]},{"id":"c47","text":"COMPLETED: Playwright installed globally. Screenshots now work anytime without setup.","createdAt":"2026-02-18T17:01:23.109Z","commentAuthorId":"9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa","replies":[]}]},{"id":"3b168e8f-d0a0-4341-a382-673d1e42f9de","comments":[{"id":"c41","text":"COMPLETED: Fixed parseDigest to extract URLs from markdown links [Title](url) in title lines","createdAt":"2026-02-18T17:01:23.109Z","commentAuthorId":"9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa","replies":[]},{"id":"c42","text":"COMPLETED: Title is now the clickable link with external link icon on hover","createdAt":"2026-02-18T17:01:23.109Z","commentAuthorId":"9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa","replies":[]}]},{"id":"5782e4a8-60e0-4b1b-87af-6fe0cf0eb1fd","comments":[{"id":"c44","text":"COMPLETED: Added /api/tasks endpoint with file-based storage","createdAt":"2026-02-18T17:01:23.109Z","commentAuthorId":"9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa","replies":[]},{"id":"c45","text":"COMPLETED: Store now syncs from server on load and auto-syncs changes","createdAt":"2026-02-18T17:01:23.109Z","commentAuthorId":"9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa","replies":[]}]},{"id":"341b7747-9a99-409e-99ea-52dfddacefe7","comments":[{"id":"c58","text":"COMPLETED: Installed react-markdown and remark-gfm","createdAt":"2026-02-18T17:01:23.109Z","commentAuthorId":"9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa","replies":[]},{"id":"c61","text":"COMPLETED: Links now open in new tab with blue styling and hover effects","createdAt":"2026-02-18T17:01:23.109Z","commentAuthorId":"9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa","replies":[]}]},{"id":"e4a28449-c065-409a-8205-cdec01c910d5","comments":[{"id":"c66","text":"All 3 apps verified to have data/ directories with JSON persistence","createdAt":"2026-02-19T13:00:00.000Z","commentAuthorId":"9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa","replies":[]},{"id":"c67","text":"Created daily-backup.sh script to commit data to Git","createdAt":"2026-02-19T13:00:00.000Z","commentAuthorId":"9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa","replies":[]},{"id":"c68","text":"Added cron job for 11:00 PM CST daily backups","createdAt":"2026-02-19T13:00:00.000Z","commentAuthorId":"9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa","replies":[]},{"id":"c69","text":"Backup logs to memory/backup.log for monitoring","createdAt":"2026-02-19T13:00:00.000Z","commentAuthorId":"9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa","replies":[]}]}] +$payload$::jsonb + ) AS x(id uuid, comments jsonb) +), +updated AS ( + UPDATE tasks t + SET comments = p.comments + FROM payload p + WHERE t.id = p.id + RETURNING t.id +) +SELECT COUNT(*) AS updated_rows FROM updated; + +COMMIT;