arkaos 4.22.0 → 4.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/THE-ARKAOS-GUIDE.md +72 -0
- package/VERSION +1 -1
- package/arka/SKILL.md +28 -6
- package/arka/skills/bootstrap-agent/SKILL.md +3 -2
- package/arka/skills/flow/SKILL.md +3 -2
- package/arka/skills/forge/SKILL.md +3 -2
- package/arka/skills/recipes/SKILL.md +3 -2
- package/arka/skills/refine/SKILL.md +3 -2
- package/arka/skills/research/SKILL.md +3 -2
- package/bin/arka-doctor +8 -0
- package/core/cognition/insights/store.py +15 -4
- package/core/forge/persistence.py +27 -9
- package/core/forge/schema.py +45 -22
- package/core/governance/evidence_checks.py +101 -9
- package/core/governance/kb_cite_check.py +16 -6
- package/core/governance/stop_lint.py +38 -11
- package/core/governance/stop_lint_telemetry.py +11 -2
- package/core/hooks/user_prompt_submit.py +21 -23
- package/core/synapse/engine.py +46 -16
- package/core/synapse/graph_context_layer.py +7 -2
- package/core/synapse/kb_cache.py +63 -16
- package/core/synapse/layers.py +93 -30
- package/core/synapse/layers_base.py +16 -0
- package/core/synapse/layers_kb.py +325 -19
- package/dashboard/app/layouts/default.vue +7 -0
- package/dashboard/app/pages/plan-canvas.vue +630 -0
- package/departments/brand/SKILL.md +3 -2
- package/departments/brand/skills/archetype-finder/SKILL.md +3 -2
- package/departments/brand/skills/colors/SKILL.md +3 -2
- package/departments/brand/skills/design-system/SKILL.md +3 -2
- package/departments/brand/skills/identity-system/SKILL.md +3 -2
- package/departments/brand/skills/logo-brief/SKILL.md +3 -2
- package/departments/brand/skills/mockup-generate/SKILL.md +3 -2
- package/departments/brand/skills/naming-evaluate/SKILL.md +3 -2
- package/departments/brand/skills/positioning-statement/SKILL.md +3 -2
- package/departments/brand/skills/primal-audit/SKILL.md +3 -2
- package/departments/brand/skills/ux-audit/SKILL.md +3 -2
- package/departments/brand/skills/voice-guide/SKILL.md +3 -2
- package/departments/brand/skills/wireframe/SKILL.md +3 -2
- package/departments/community/SKILL.md +3 -2
- package/departments/community/skills/ai-community/SKILL.md +3 -2
- package/departments/community/skills/betting-setup/SKILL.md +3 -2
- package/departments/community/skills/business-model/SKILL.md +3 -2
- package/departments/community/skills/content-calendar/SKILL.md +3 -2
- package/departments/community/skills/events-plan/SKILL.md +3 -2
- package/departments/community/skills/gamification-design/SKILL.md +3 -2
- package/departments/community/skills/growth-plan/SKILL.md +3 -2
- package/departments/community/skills/metrics-track/SKILL.md +3 -2
- package/departments/community/skills/moderation/SKILL.md +3 -2
- package/departments/community/skills/monetize-plan/SKILL.md +3 -2
- package/departments/community/skills/niche-setup/SKILL.md +3 -2
- package/departments/community/skills/onboarding-flow/SKILL.md +3 -2
- package/departments/community/skills/platform-select/SKILL.md +3 -2
- package/departments/content/SKILL.md +3 -2
- package/departments/content/skills/ai-workflow/SKILL.md +3 -2
- package/departments/content/skills/analytics/SKILL.md +3 -2
- package/departments/content/skills/calendar/SKILL.md +3 -2
- package/departments/content/skills/content-system/SKILL.md +3 -2
- package/departments/content/skills/monetization-plan/SKILL.md +3 -2
- package/departments/content/skills/newsletter-write/SKILL.md +3 -2
- package/departments/content/skills/platform-optimize/SKILL.md +3 -2
- package/departments/content/skills/repurpose-plan/SKILL.md +3 -2
- package/departments/content/skills/research-compile/SKILL.md +3 -2
- package/departments/content/skills/script-structure/SKILL.md +3 -2
- package/departments/content/skills/short-form/SKILL.md +3 -2
- package/departments/content/skills/thumbnail-package/SKILL.md +3 -2
- package/departments/content/skills/trend-hunt/SKILL.md +3 -2
- package/departments/content/skills/video-produce/SKILL.md +3 -2
- package/departments/content/skills/video-setup/SKILL.md +3 -2
- package/departments/content/skills/viral-design/SKILL.md +3 -2
- package/departments/content/skills/youtube-strategy/SKILL.md +3 -2
- package/departments/dev/SKILL.md +3 -2
- package/departments/dev/skills/ai-assisted-dev/SKILL.md +3 -2
- package/departments/dev/skills/animated-website/SKILL.md +7 -0
- package/departments/dev/skills/architecture-design/SKILL.md +3 -2
- package/departments/dev/skills/code-review/SKILL.md +3 -2
- package/departments/dev/skills/db-design/SKILL.md +3 -2
- package/departments/dev/skills/ddd-model/SKILL.md +3 -2
- package/departments/dev/skills/demo-gif/SKILL.md +3 -2
- package/departments/dev/skills/deploy/SKILL.md +3 -2
- package/departments/dev/skills/devops-pipeline/SKILL.md +3 -2
- package/departments/dev/skills/docs/SKILL.md +3 -2
- package/departments/dev/skills/mcp/SKILL.md +3 -2
- package/departments/dev/skills/performance-audit/SKILL.md +3 -2
- package/departments/dev/skills/refactor-plan/SKILL.md +3 -2
- package/departments/dev/skills/research/SKILL.md +3 -2
- package/departments/dev/skills/security-compliance/SKILL.md +3 -2
- package/departments/dev/skills/stack-check/SKILL.md +3 -2
- package/departments/ecom/SKILL.md +3 -2
- package/departments/ecom/skills/analytics/SKILL.md +3 -2
- package/departments/ecom/skills/browse-competitor/SKILL.md +3 -2
- package/departments/ecom/skills/cart-recovery/SKILL.md +3 -2
- package/departments/ecom/skills/cro-optimize/SKILL.md +3 -2
- package/departments/ecom/skills/customer-journey/SKILL.md +3 -2
- package/departments/ecom/skills/fulfillment-plan/SKILL.md +3 -2
- package/departments/ecom/skills/marketplace-manage/SKILL.md +3 -2
- package/departments/ecom/skills/pricing-strategy/SKILL.md +3 -2
- package/departments/ecom/skills/product-launch/SKILL.md +3 -2
- package/departments/ecom/skills/rfm-segment/SKILL.md +3 -2
- package/departments/ecom/skills/social-commerce/SKILL.md +3 -2
- package/departments/ecom/skills/store-audit/SKILL.md +3 -2
- package/departments/ecom/skills/subscription-model/SKILL.md +3 -2
- package/departments/finance/SKILL.md +3 -2
- package/departments/finance/skills/budget-plan/SKILL.md +3 -2
- package/departments/finance/skills/cashflow-forecast/SKILL.md +3 -2
- package/departments/finance/skills/ciso-advisor/SKILL.md +3 -2
- package/departments/finance/skills/financial-model/SKILL.md +3 -2
- package/departments/finance/skills/pitch-deck/SKILL.md +3 -2
- package/departments/finance/skills/scenario-analysis/SKILL.md +3 -2
- package/departments/finance/skills/unit-economics/SKILL.md +3 -2
- package/departments/finance/skills/valuation-model/SKILL.md +3 -2
- package/departments/kb/SKILL.md +3 -2
- package/departments/kb/skills/ai-research/SKILL.md +3 -2
- package/departments/kb/skills/competitive-intel/SKILL.md +3 -2
- package/departments/kb/skills/doc-extraction/SKILL.md +3 -2
- package/departments/kb/skills/doc-redaction/SKILL.md +3 -2
- package/departments/kb/skills/knowledge-ops/SKILL.md +3 -2
- package/departments/kb/skills/knowledge-review/SKILL.md +3 -2
- package/departments/kb/skills/learn-content/SKILL.md +3 -2
- package/departments/kb/skills/moc-create/SKILL.md +3 -2
- package/departments/kb/skills/persona-build/SKILL.md +3 -2
- package/departments/kb/skills/research-plan/SKILL.md +3 -2
- package/departments/kb/skills/search-kb/SKILL.md +3 -2
- package/departments/kb/skills/source-evaluate/SKILL.md +3 -2
- package/departments/kb/skills/taxonomy-manage/SKILL.md +3 -2
- package/departments/kb/skills/write-as-persona/SKILL.md +3 -2
- package/departments/landing/SKILL.md +3 -2
- package/departments/landing/skills/ab-test/SKILL.md +3 -2
- package/departments/landing/skills/affiliate-bridge/SKILL.md +3 -2
- package/departments/landing/skills/awareness-diagnose/SKILL.md +3 -2
- package/departments/landing/skills/email-sequence/SKILL.md +3 -2
- package/departments/landing/skills/funnel-metrics/SKILL.md +3 -2
- package/departments/landing/skills/headline-write/SKILL.md +3 -2
- package/departments/landing/skills/launch-sequence/SKILL.md +3 -2
- package/departments/landing/skills/offer-create/SKILL.md +3 -2
- package/departments/landing/skills/optimize-page/SKILL.md +3 -2
- package/departments/landing/skills/page-architect/SKILL.md +3 -2
- package/departments/landing/skills/persuasion-apply/SKILL.md +3 -2
- package/departments/landing/skills/webinar-funnel/SKILL.md +3 -2
- package/departments/leadership/SKILL.md +3 -2
- package/departments/leadership/skills/change-manage/SKILL.md +3 -2
- package/departments/leadership/skills/conflict-resolve/SKILL.md +3 -2
- package/departments/leadership/skills/culture-audit/SKILL.md +3 -2
- package/departments/leadership/skills/delegation-matrix/SKILL.md +3 -2
- package/departments/leadership/skills/disc-assess/SKILL.md +3 -2
- package/departments/leadership/skills/feedback-give/SKILL.md +3 -2
- package/departments/leadership/skills/hiring-plan/SKILL.md +3 -2
- package/departments/leadership/skills/performance-review/SKILL.md +3 -2
- package/departments/marketing/SKILL.md +3 -2
- package/departments/marketing/skills/ab-test/SKILL.md +3 -2
- package/departments/marketing/skills/analytics-report/SKILL.md +3 -2
- package/departments/marketing/skills/audience-segment/SKILL.md +3 -2
- package/departments/marketing/skills/calendar-plan/SKILL.md +3 -2
- package/departments/marketing/skills/competitor-analysis/SKILL.md +3 -2
- package/departments/marketing/skills/content-audit/SKILL.md +3 -2
- package/departments/marketing/skills/email-sequence/SKILL.md +3 -2
- package/departments/marketing/skills/growth-loop/SKILL.md +3 -2
- package/departments/marketing/skills/marketing-automation/SKILL.md +3 -2
- package/departments/marketing/skills/paid-campaign/SKILL.md +3 -2
- package/departments/marketing/skills/programmatic-seo/SKILL.md +3 -2
- package/departments/marketing/skills/seo-audit/SKILL.md +3 -2
- package/departments/marketing/skills/social-strategy/SKILL.md +3 -2
- package/departments/ops/SKILL.md +3 -2
- package/departments/ops/skills/bottleneck-find/SKILL.md +3 -2
- package/departments/ops/skills/dashboard-build/SKILL.md +3 -2
- package/departments/ops/skills/gdpr-compliance/SKILL.md +3 -2
- package/departments/ops/skills/github-ops/SKILL.md +3 -2
- package/departments/ops/skills/gtd-setup/SKILL.md +3 -2
- package/departments/ops/skills/integration-design/SKILL.md +3 -2
- package/departments/ops/skills/iso27001/SKILL.md +3 -2
- package/departments/ops/skills/lean-audit/SKILL.md +3 -2
- package/departments/ops/skills/metrics-dashboard/SKILL.md +3 -2
- package/departments/ops/skills/n8n-flow/SKILL.md +3 -2
- package/departments/ops/skills/quality-management/SKILL.md +3 -2
- package/departments/ops/skills/risk-management/SKILL.md +3 -2
- package/departments/ops/skills/soc2-compliance/SKILL.md +3 -2
- package/departments/ops/skills/sop-create/SKILL.md +3 -2
- package/departments/ops/skills/terminal-ops/SKILL.md +3 -2
- package/departments/ops/skills/workflow-automate/SKILL.md +3 -2
- package/departments/ops/skills/zapier-flow/SKILL.md +3 -2
- package/departments/org/SKILL.md +3 -2
- package/departments/org/skills/compensation-plan/SKILL.md +3 -2
- package/departments/org/skills/culture-define/SKILL.md +3 -2
- package/departments/org/skills/decision-framework/SKILL.md +3 -2
- package/departments/org/skills/hiring-plan/SKILL.md +3 -2
- package/departments/org/skills/meeting-optimize/SKILL.md +3 -2
- package/departments/org/skills/onboarding-design/SKILL.md +3 -2
- package/departments/org/skills/org-design/SKILL.md +3 -2
- package/departments/org/skills/remote-setup/SKILL.md +3 -2
- package/departments/org/skills/sop-process/SKILL.md +3 -2
- package/departments/org/skills/team-assess/SKILL.md +3 -2
- package/departments/pm/SKILL.md +3 -2
- package/departments/pm/skills/backlog-groom/SKILL.md +3 -2
- package/departments/pm/skills/discovery-plan/SKILL.md +3 -2
- package/departments/pm/skills/estimate-forecast/SKILL.md +3 -2
- package/departments/pm/skills/impact-map/SKILL.md +3 -2
- package/departments/pm/skills/kanban-setup/SKILL.md +3 -2
- package/departments/pm/skills/risk-register/SKILL.md +3 -2
- package/departments/pm/skills/roadmap-build/SKILL.md +3 -2
- package/departments/pm/skills/sprint-plan/SKILL.md +3 -2
- package/departments/pm/skills/stakeholder-map/SKILL.md +3 -2
- package/departments/pm/skills/standup-run/SKILL.md +3 -2
- package/departments/pm/skills/story-write/SKILL.md +3 -2
- package/departments/saas/SKILL.md +3 -2
- package/departments/saas/skills/benchmark-compare/SKILL.md +3 -2
- package/departments/saas/skills/churn-analysis/SKILL.md +3 -2
- package/departments/saas/skills/customer-success/SKILL.md +3 -2
- package/departments/saas/skills/growth-plan/SKILL.md +3 -2
- package/departments/saas/skills/gtm-strategy/SKILL.md +3 -2
- package/departments/saas/skills/launch-execute/SKILL.md +3 -2
- package/departments/saas/skills/metrics-dashboard/SKILL.md +3 -2
- package/departments/saas/skills/micro-saas-stack/SKILL.md +3 -2
- package/departments/saas/skills/mvp-build/SKILL.md +3 -2
- package/departments/saas/skills/niche-evaluate/SKILL.md +3 -2
- package/departments/saas/skills/onboarding-optimize/SKILL.md +3 -2
- package/departments/saas/skills/plg-setup/SKILL.md +3 -2
- package/departments/saas/skills/pricing-strategy/SKILL.md +3 -2
- package/departments/saas/skills/validate-idea/SKILL.md +3 -2
- package/departments/sales/SKILL.md +3 -2
- package/departments/sales/skills/challenger-sell/SKILL.md +3 -2
- package/departments/sales/skills/deal-qualify/SKILL.md +3 -2
- package/departments/sales/skills/discovery-call/SKILL.md +3 -2
- package/departments/sales/skills/forecast-revenue/SKILL.md +3 -2
- package/departments/sales/skills/negotiate-plan/SKILL.md +3 -2
- package/departments/sales/skills/objection-handle/SKILL.md +3 -2
- package/departments/sales/skills/pipeline-manage/SKILL.md +3 -2
- package/departments/sales/skills/pricing-negotiate/SKILL.md +3 -2
- package/departments/strategy/SKILL.md +3 -2
- package/departments/strategy/skills/blue-ocean/SKILL.md +3 -2
- package/departments/strategy/skills/bmc/SKILL.md +3 -2
- package/departments/strategy/skills/board-advisor/SKILL.md +3 -2
- package/departments/strategy/skills/cto-advisor/SKILL.md +3 -2
- package/departments/strategy/skills/extract-data/SKILL.md +3 -2
- package/departments/strategy/skills/five-forces/SKILL.md +3 -2
- package/departments/strategy/skills/growth-strategy/SKILL.md +3 -2
- package/departments/strategy/skills/moat-analysis/SKILL.md +3 -2
- package/departments/strategy/skills/position/SKILL.md +3 -2
- package/departments/strategy/skills/scenario-plan/SKILL.md +3 -2
- package/installer/config-seed.js +81 -25
- package/installer/graphify.js +340 -0
- package/installer/index.js +8 -1
- package/installer/keys.js +18 -3
- package/installer/update.js +8 -1
- package/knowledge/skills-manifest.json +1 -1
- package/mcps/registry.json +9 -9
- package/mcps/scripts/apply-mcps.sh +6 -2
- package/package.json +2 -1
- package/pyproject.toml +1 -1
- package/scripts/dashboard-api.py +336 -124
- package/scripts/guide_gen.py +139 -0
- package/scripts/migrate_skills_kb_first.py +3 -2
- package/scripts/synapse-bridge.py +9 -1
|
@@ -0,0 +1,630 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// Plan Canvas — review and decide on Forge plans (design direction
|
|
3
|
+
// validated by brand 2026-07-20: master-detail, Decision Rail as the
|
|
4
|
+
// page's single EKG-family signature, green budget = awaiting-review
|
|
5
|
+
// accent + approved badge + Approve button, keyboard-first).
|
|
6
|
+
|
|
7
|
+
interface PlanSummary {
|
|
8
|
+
id: string
|
|
9
|
+
name: string
|
|
10
|
+
status: string
|
|
11
|
+
tier: string
|
|
12
|
+
confidence: number
|
|
13
|
+
created_at: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface PlanPhase {
|
|
17
|
+
name: string
|
|
18
|
+
department: string
|
|
19
|
+
agents: string[]
|
|
20
|
+
deliverables: string[]
|
|
21
|
+
acceptance_criteria: string[]
|
|
22
|
+
depends_on: string[]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface PlanDetail {
|
|
26
|
+
id: string
|
|
27
|
+
name: string
|
|
28
|
+
created_at: string
|
|
29
|
+
forged_by: string
|
|
30
|
+
goal: string
|
|
31
|
+
status: string
|
|
32
|
+
approved_at: string | null
|
|
33
|
+
approved_by: string | null
|
|
34
|
+
rejected_at: string | null
|
|
35
|
+
rejected_by: string | null
|
|
36
|
+
executed_at: string | null
|
|
37
|
+
review_note: string | null
|
|
38
|
+
plan_phases: PlanPhase[]
|
|
39
|
+
complexity: { score: number, tier: string }
|
|
40
|
+
critic: {
|
|
41
|
+
confidence: number
|
|
42
|
+
// IdentifiedRisk serializes risk/mitigation/severity, not description.
|
|
43
|
+
risks: { risk?: string, mitigation?: string, severity?: string }[]
|
|
44
|
+
rejected_elements: { element?: string, reason?: string }[]
|
|
45
|
+
}
|
|
46
|
+
governance: {
|
|
47
|
+
constitution_check: string
|
|
48
|
+
violations: string[]
|
|
49
|
+
quality_gate_required: boolean
|
|
50
|
+
}
|
|
51
|
+
execution_path: { type: string, target: string, departments: string[] }
|
|
52
|
+
degraded: boolean
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const { fetchApi, apiBase } = useApi()
|
|
56
|
+
const toast = useToast()
|
|
57
|
+
const confirm = useConfirmDialog()
|
|
58
|
+
|
|
59
|
+
const { data, status, error, refresh } = await fetchApi<{
|
|
60
|
+
plans: PlanSummary[]
|
|
61
|
+
active_id: string | null
|
|
62
|
+
}>('/api/plans')
|
|
63
|
+
|
|
64
|
+
const plans = computed(() => data.value?.plans ?? [])
|
|
65
|
+
const activeId = computed(() => data.value?.active_id ?? null)
|
|
66
|
+
const awaiting = computed(() =>
|
|
67
|
+
plans.value.filter(p => ['draft', 'reviewing'].includes(p.status)).length
|
|
68
|
+
)
|
|
69
|
+
const executing = computed(() =>
|
|
70
|
+
plans.value.filter(p => p.status === 'executing').length
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
const selectedId = ref<string | null>(null)
|
|
74
|
+
const detailPath = computed(() =>
|
|
75
|
+
selectedId.value ? `/api/plans/${selectedId.value}` : ''
|
|
76
|
+
)
|
|
77
|
+
const {
|
|
78
|
+
data: detailData,
|
|
79
|
+
status: detailStatus,
|
|
80
|
+
refresh: refreshDetail
|
|
81
|
+
} = await fetchApi<{ plan?: PlanDetail, legacy?: boolean, error?: string }>(
|
|
82
|
+
() => detailPath.value,
|
|
83
|
+
{ immediate: false, watch: false }
|
|
84
|
+
)
|
|
85
|
+
// Explicit over reactive-URL magic: with immediate:false the watcher
|
|
86
|
+
// chain proved unreliable in the production build — refetch on select.
|
|
87
|
+
watch(selectedId, (id) => {
|
|
88
|
+
if (id) refreshDetail()
|
|
89
|
+
})
|
|
90
|
+
const plan = computed(() => detailData.value?.plan ?? null)
|
|
91
|
+
const legacy = computed(() => detailData.value?.legacy === true)
|
|
92
|
+
|
|
93
|
+
// ── status vocabulary (green stays scarce: approved only) ──────────────
|
|
94
|
+
type BadgeColor = 'error' | 'primary' | 'info' | 'warning' | 'neutral'
|
|
95
|
+
type BadgeVariant = 'outline' | 'subtle'
|
|
96
|
+
const STATUS_BADGE: Record<string, { color: BadgeColor, variant: BadgeVariant }> = {
|
|
97
|
+
draft: { color: 'neutral', variant: 'outline' },
|
|
98
|
+
reviewing: { color: 'warning', variant: 'subtle' },
|
|
99
|
+
approved: { color: 'primary', variant: 'subtle' },
|
|
100
|
+
executing: { color: 'info', variant: 'subtle' },
|
|
101
|
+
completed: { color: 'neutral', variant: 'subtle' },
|
|
102
|
+
rejected: { color: 'error', variant: 'subtle' },
|
|
103
|
+
cancelled: { color: 'neutral', variant: 'outline' },
|
|
104
|
+
archived: { color: 'neutral', variant: 'outline' }
|
|
105
|
+
}
|
|
106
|
+
const badgeFor = (s: string) => STATUS_BADGE[s] ?? STATUS_BADGE.draft!
|
|
107
|
+
|
|
108
|
+
const decidable = computed(() =>
|
|
109
|
+
plan.value && !legacy.value
|
|
110
|
+
? ['draft', 'reviewing'].includes(plan.value.status)
|
|
111
|
+
: false
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
// ── selection + keyboard (j/k/enter/esc/a/r; inputs are guarded by
|
|
115
|
+
// Nuxt UI's default usingInput=false) ─────────────────────────────────
|
|
116
|
+
const cursor = ref(0)
|
|
117
|
+
watch(plans, (list) => {
|
|
118
|
+
if (cursor.value >= list.length) cursor.value = Math.max(0, list.length - 1)
|
|
119
|
+
})
|
|
120
|
+
const select = (id: string) => {
|
|
121
|
+
selectedId.value = id
|
|
122
|
+
cursor.value = plans.value.findIndex(p => p.id === id)
|
|
123
|
+
}
|
|
124
|
+
defineShortcuts({
|
|
125
|
+
j: () => {
|
|
126
|
+
if (plans.value.length) {
|
|
127
|
+
cursor.value = Math.min(cursor.value + 1, plans.value.length - 1)
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
k: () => {
|
|
131
|
+
if (plans.value.length) cursor.value = Math.max(cursor.value - 1, 0)
|
|
132
|
+
},
|
|
133
|
+
enter: () => {
|
|
134
|
+
const target = plans.value[cursor.value]
|
|
135
|
+
if (target) select(target.id)
|
|
136
|
+
},
|
|
137
|
+
escape: () => { selectedId.value = null },
|
|
138
|
+
a: () => { if (decidable.value) decide('approve') },
|
|
139
|
+
r: () => { if (decidable.value) decide('reject') }
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
// ── tabs + raw escape-hatch ────────────────────────────────────────────
|
|
143
|
+
const tab = ref<'phases' | 'forge'>('phases')
|
|
144
|
+
const showRaw = ref(false)
|
|
145
|
+
watch(selectedId, () => {
|
|
146
|
+
tab.value = 'phases'
|
|
147
|
+
showRaw.value = false
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
// ── decision ───────────────────────────────────────────────────────────
|
|
151
|
+
const note = ref('')
|
|
152
|
+
const deciding = ref(false)
|
|
153
|
+
watch(selectedId, () => {
|
|
154
|
+
note.value = ''
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
async function decide(action: 'approve' | 'reject') {
|
|
158
|
+
if (!plan.value || deciding.value) return
|
|
159
|
+
if (action === 'reject') {
|
|
160
|
+
const ok = await confirm({
|
|
161
|
+
title: `Reject "${plan.value.name}"`,
|
|
162
|
+
description: 'The plan moves to rejected — a terminal state. '
|
|
163
|
+
+ 'Your note stays on the record as the rationale.',
|
|
164
|
+
confirmLabel: 'Reject plan',
|
|
165
|
+
variant: 'danger'
|
|
166
|
+
})
|
|
167
|
+
if (!ok) return
|
|
168
|
+
}
|
|
169
|
+
deciding.value = true
|
|
170
|
+
try {
|
|
171
|
+
const result = await $fetch<{ status?: string, error?: string }>(
|
|
172
|
+
`${apiBase}/api/plans/${plan.value.id}/decision`,
|
|
173
|
+
{ method: 'POST', body: { action, note: note.value } }
|
|
174
|
+
)
|
|
175
|
+
if (result.error) {
|
|
176
|
+
toast.add({ title: 'Decision refused', description: result.error, color: 'error' })
|
|
177
|
+
} else {
|
|
178
|
+
toast.add({
|
|
179
|
+
title: action === 'approve' ? 'Plan approved' : 'Plan rejected',
|
|
180
|
+
color: action === 'approve' ? 'primary' : 'neutral'
|
|
181
|
+
})
|
|
182
|
+
note.value = ''
|
|
183
|
+
await Promise.all([refresh(), refreshDetail()])
|
|
184
|
+
}
|
|
185
|
+
} catch {
|
|
186
|
+
toast.add({ title: 'Decision failed', description: 'API unreachable.', color: 'error' })
|
|
187
|
+
} finally {
|
|
188
|
+
deciding.value = false
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// ── Decision Rail (the signature): static line, real trail only ────────
|
|
193
|
+
const RAIL = ['draft', 'reviewing', 'approved', 'executing', 'completed']
|
|
194
|
+
const NEGATIVE = ['rejected', 'cancelled']
|
|
195
|
+
const railStations = computed(() => {
|
|
196
|
+
if (!plan.value) return []
|
|
197
|
+
const p = plan.value
|
|
198
|
+
const negative = NEGATIVE.includes(p.status)
|
|
199
|
+
const reachedIndex = negative
|
|
200
|
+
? RAIL.indexOf('reviewing')
|
|
201
|
+
: RAIL.indexOf(p.status === 'archived' ? 'completed' : p.status)
|
|
202
|
+
return RAIL.map((stage, i) => ({
|
|
203
|
+
stage,
|
|
204
|
+
reached: i <= reachedIndex,
|
|
205
|
+
current: !negative && stage === (p.status === 'archived' ? 'completed' : p.status),
|
|
206
|
+
detail: stage === 'draft' && p.created_at
|
|
207
|
+
? `forged ${formatWhen(p.created_at)}${p.forged_by ? ` · ${p.forged_by}` : ''}`
|
|
208
|
+
: stage === 'approved' && p.approved_at
|
|
209
|
+
? `${formatWhen(p.approved_at)}${p.approved_by ? ` · ${p.approved_by}` : ''}`
|
|
210
|
+
: stage === 'executing' && p.executed_at
|
|
211
|
+
? formatWhen(p.executed_at)
|
|
212
|
+
: '',
|
|
213
|
+
note: stage === 'approved' && p.status !== 'rejected' ? p.review_note : null
|
|
214
|
+
}))
|
|
215
|
+
})
|
|
216
|
+
const negativeTerminal = computed(() => {
|
|
217
|
+
if (!plan.value || !NEGATIVE.includes(plan.value.status)) return null
|
|
218
|
+
const p = plan.value
|
|
219
|
+
const trail = p.rejected_at
|
|
220
|
+
? `${formatWhen(p.rejected_at)}${p.rejected_by ? ` · ${p.rejected_by}` : ''}`
|
|
221
|
+
: ''
|
|
222
|
+
return {
|
|
223
|
+
stage: p.status,
|
|
224
|
+
detail: trail,
|
|
225
|
+
note: p.review_note
|
|
226
|
+
}
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
function formatWhen(iso: string): string {
|
|
230
|
+
const d = new Date(iso)
|
|
231
|
+
return Number.isNaN(d.getTime())
|
|
232
|
+
? iso
|
|
233
|
+
: d.toLocaleDateString('en-GB', { day: '2-digit', month: 'short' })
|
|
234
|
+
+ ' ' + d.toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit' })
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// ── polling (ArkaLiveFeed cadence; paused when the tab is hidden) ──────
|
|
238
|
+
const visibility = useDocumentVisibility()
|
|
239
|
+
let poll: ReturnType<typeof setInterval> | undefined
|
|
240
|
+
onMounted(() => {
|
|
241
|
+
poll = setInterval(() => {
|
|
242
|
+
if (visibility.value === 'visible') refresh()
|
|
243
|
+
}, 15_000)
|
|
244
|
+
})
|
|
245
|
+
onBeforeUnmount(() => {
|
|
246
|
+
if (poll) clearInterval(poll)
|
|
247
|
+
})
|
|
248
|
+
</script>
|
|
249
|
+
|
|
250
|
+
<template>
|
|
251
|
+
<UDashboardPanel id="plan-canvas">
|
|
252
|
+
<template #header>
|
|
253
|
+
<UDashboardNavbar title="Plan Canvas">
|
|
254
|
+
<template #leading>
|
|
255
|
+
<UDashboardSidebarCollapse />
|
|
256
|
+
</template>
|
|
257
|
+
<template #right>
|
|
258
|
+
<UButton
|
|
259
|
+
icon="i-lucide-refresh-cw"
|
|
260
|
+
color="neutral"
|
|
261
|
+
variant="ghost"
|
|
262
|
+
aria-label="Refresh plans"
|
|
263
|
+
@click="() => refresh()"
|
|
264
|
+
/>
|
|
265
|
+
</template>
|
|
266
|
+
</UDashboardNavbar>
|
|
267
|
+
</template>
|
|
268
|
+
|
|
269
|
+
<template #body>
|
|
270
|
+
<DashboardState
|
|
271
|
+
:status="status"
|
|
272
|
+
:error="error"
|
|
273
|
+
:empty="!plans.length"
|
|
274
|
+
empty-title="No forge plans yet"
|
|
275
|
+
empty-description="Plans land here when The Forge persists them — run /arka forge on a task."
|
|
276
|
+
empty-icon="i-lucide-drafting-compass"
|
|
277
|
+
:on-retry="() => refresh()"
|
|
278
|
+
>
|
|
279
|
+
<div class="mx-auto w-full max-w-6xl space-y-10 py-2">
|
|
280
|
+
<ArkaPageHero
|
|
281
|
+
numeral="I"
|
|
282
|
+
label="plan canvas"
|
|
283
|
+
title="The plan is the contract."
|
|
284
|
+
subtitle="Read deeply, decide once, leave a trail — approval is an operator act, not a formality."
|
|
285
|
+
>
|
|
286
|
+
<template #stats>
|
|
287
|
+
<div class="mt-4 grid grid-cols-1 gap-4 sm:grid-cols-2">
|
|
288
|
+
<ArkaStatCard
|
|
289
|
+
label="awaiting review"
|
|
290
|
+
:value="awaiting"
|
|
291
|
+
accent
|
|
292
|
+
hint="draft + reviewing — the number that changes your next action"
|
|
293
|
+
/>
|
|
294
|
+
<ArkaStatCard
|
|
295
|
+
label="executing"
|
|
296
|
+
:value="executing"
|
|
297
|
+
hint="approved and in motion"
|
|
298
|
+
/>
|
|
299
|
+
</div>
|
|
300
|
+
</template>
|
|
301
|
+
</ArkaPageHero>
|
|
302
|
+
|
|
303
|
+
<ArkaSection numeral="II" label="queue · review">
|
|
304
|
+
<div class="grid grid-cols-1 gap-6 lg:grid-cols-5">
|
|
305
|
+
<!-- master: the queue -->
|
|
306
|
+
<div class="lg:col-span-2 space-y-1" role="listbox" aria-label="Forge plans">
|
|
307
|
+
<button
|
|
308
|
+
v-for="(p, i) in plans"
|
|
309
|
+
:key="p.id"
|
|
310
|
+
type="button"
|
|
311
|
+
role="option"
|
|
312
|
+
:aria-selected="selectedId === p.id"
|
|
313
|
+
class="w-full rounded-md border px-3 py-2.5 text-left transition-colors duration-150 focus-visible:outline-2 focus-visible:outline-primary"
|
|
314
|
+
:class="[
|
|
315
|
+
selectedId === p.id
|
|
316
|
+
? 'border-[var(--ui-border-accented)] bg-[var(--ui-bg-elevated)]'
|
|
317
|
+
: 'border-transparent hover:bg-[var(--ui-bg-elevated)]',
|
|
318
|
+
cursor === i ? 'ring-1 ring-[var(--ui-border-accented)]' : ''
|
|
319
|
+
]"
|
|
320
|
+
@click="select(p.id)"
|
|
321
|
+
>
|
|
322
|
+
<div class="flex items-center justify-between gap-2">
|
|
323
|
+
<span class="truncate text-sm font-medium">
|
|
324
|
+
{{ p.name || p.id }}
|
|
325
|
+
</span>
|
|
326
|
+
<UBadge
|
|
327
|
+
:color="badgeFor(p.status).color"
|
|
328
|
+
:variant="badgeFor(p.status).variant"
|
|
329
|
+
size="sm"
|
|
330
|
+
class="shrink-0 capitalize"
|
|
331
|
+
>
|
|
332
|
+
<UIcon
|
|
333
|
+
v-if="p.status === 'completed'"
|
|
334
|
+
name="i-lucide-check"
|
|
335
|
+
class="size-3"
|
|
336
|
+
/>
|
|
337
|
+
{{ p.status }}
|
|
338
|
+
</UBadge>
|
|
339
|
+
</div>
|
|
340
|
+
<div class="mt-1 flex items-center gap-3 text-xs text-muted">
|
|
341
|
+
<span class="arka-data">{{ p.tier }}</span>
|
|
342
|
+
<span class="arka-data">conf {{ (p.confidence ?? 0).toFixed(2) }}</span>
|
|
343
|
+
<span v-if="p.id === activeId" class="arka-eyebrow">active</span>
|
|
344
|
+
</div>
|
|
345
|
+
</button>
|
|
346
|
+
<p class="px-3 pt-2 text-[11px] text-muted">
|
|
347
|
+
<kbd>j</kbd>/<kbd>k</kbd> navigate · <kbd>↵</kbd> open ·
|
|
348
|
+
<kbd>esc</kbd> close · <kbd>a</kbd> approve · <kbd>r</kbd> reject
|
|
349
|
+
</p>
|
|
350
|
+
</div>
|
|
351
|
+
|
|
352
|
+
<!-- detail: review pane + Decision Rail -->
|
|
353
|
+
<div class="lg:col-span-3">
|
|
354
|
+
<ArkaGlowCard v-if="plan" :live="decidable">
|
|
355
|
+
<div class="grid grid-cols-1 gap-6 xl:grid-cols-[1fr_215px]">
|
|
356
|
+
<div class="min-w-0 space-y-4">
|
|
357
|
+
<header class="space-y-1">
|
|
358
|
+
<div class="flex items-start justify-between gap-3">
|
|
359
|
+
<h2 class="arka-serif-title text-2xl leading-tight">
|
|
360
|
+
{{ plan.name || plan.id }}
|
|
361
|
+
</h2>
|
|
362
|
+
<UButton
|
|
363
|
+
:label="showRaw ? 'hide raw' : 'raw'"
|
|
364
|
+
color="neutral"
|
|
365
|
+
variant="ghost"
|
|
366
|
+
size="xs"
|
|
367
|
+
icon="i-lucide-braces"
|
|
368
|
+
:aria-expanded="showRaw"
|
|
369
|
+
@click="showRaw = !showRaw"
|
|
370
|
+
/>
|
|
371
|
+
</div>
|
|
372
|
+
<p class="arka-data text-xs text-muted">
|
|
373
|
+
{{ plan.id }}
|
|
374
|
+
</p>
|
|
375
|
+
<p v-if="plan.goal" class="text-sm text-muted">
|
|
376
|
+
{{ plan.goal }}
|
|
377
|
+
</p>
|
|
378
|
+
<UBadge
|
|
379
|
+
v-if="plan.degraded"
|
|
380
|
+
color="warning"
|
|
381
|
+
variant="subtle"
|
|
382
|
+
size="sm"
|
|
383
|
+
>
|
|
384
|
+
degraded forge — constitution phases only
|
|
385
|
+
</UBadge>
|
|
386
|
+
<UBadge
|
|
387
|
+
v-if="legacy"
|
|
388
|
+
color="neutral"
|
|
389
|
+
variant="outline"
|
|
390
|
+
size="sm"
|
|
391
|
+
>
|
|
392
|
+
legacy format — read-only
|
|
393
|
+
</UBadge>
|
|
394
|
+
</header>
|
|
395
|
+
|
|
396
|
+
<pre
|
|
397
|
+
v-if="showRaw"
|
|
398
|
+
class="arka-data max-h-72 overflow-auto rounded-md border border-[var(--ui-border)] bg-[var(--ui-bg)] p-3 text-[11px] leading-relaxed"
|
|
399
|
+
>{{ JSON.stringify(plan, null, 2) }}</pre>
|
|
400
|
+
|
|
401
|
+
<nav class="flex gap-1 border-b border-[var(--ui-border)]" aria-label="Plan views">
|
|
402
|
+
<button
|
|
403
|
+
v-for="t in (['phases', 'forge'] as const)"
|
|
404
|
+
:key="t"
|
|
405
|
+
type="button"
|
|
406
|
+
class="arka-eyebrow px-3 py-2 transition-colors duration-150"
|
|
407
|
+
:class="tab === t
|
|
408
|
+
? 'border-b-2 border-primary text-[var(--ui-text)]'
|
|
409
|
+
: 'text-muted hover:text-[var(--ui-text)]'"
|
|
410
|
+
:aria-current="tab === t ? 'true' : undefined"
|
|
411
|
+
@click="tab = t"
|
|
412
|
+
>
|
|
413
|
+
{{ t }}
|
|
414
|
+
</button>
|
|
415
|
+
</nav>
|
|
416
|
+
|
|
417
|
+
<!-- phases: stacked cards to READ (the rail is the
|
|
418
|
+
page's only vertical stepper) -->
|
|
419
|
+
<div v-if="tab === 'phases'" class="space-y-3">
|
|
420
|
+
<div
|
|
421
|
+
v-for="(phase, i) in plan.plan_phases"
|
|
422
|
+
:key="phase.name"
|
|
423
|
+
class="rounded-md border border-[var(--ui-border)] p-3"
|
|
424
|
+
>
|
|
425
|
+
<div class="flex items-center justify-between gap-2">
|
|
426
|
+
<p class="text-sm font-medium">
|
|
427
|
+
<span class="arka-numeral mr-1.5">{{ i + 1 }}</span>
|
|
428
|
+
{{ phase.name }}
|
|
429
|
+
</p>
|
|
430
|
+
<span class="arka-eyebrow shrink-0">{{ phase.department }}</span>
|
|
431
|
+
</div>
|
|
432
|
+
<ul
|
|
433
|
+
v-if="phase.deliverables.length"
|
|
434
|
+
class="mt-2 space-y-1 text-xs text-muted"
|
|
435
|
+
>
|
|
436
|
+
<li v-for="d in phase.deliverables" :key="d" class="flex gap-2">
|
|
437
|
+
<span aria-hidden="true">—</span><span>{{ d }}</span>
|
|
438
|
+
</li>
|
|
439
|
+
</ul>
|
|
440
|
+
<p
|
|
441
|
+
v-if="phase.acceptance_criteria.length"
|
|
442
|
+
class="mt-2 text-[11px] text-muted"
|
|
443
|
+
>
|
|
444
|
+
<span class="arka-eyebrow">accepts</span>
|
|
445
|
+
{{ phase.acceptance_criteria.join(' · ') }}
|
|
446
|
+
</p>
|
|
447
|
+
</div>
|
|
448
|
+
<p v-if="!plan.plan_phases.length" class="text-sm text-muted">
|
|
449
|
+
This plan carries no phases — inspect the raw payload.
|
|
450
|
+
</p>
|
|
451
|
+
</div>
|
|
452
|
+
|
|
453
|
+
<!-- forge: complexity, critic, governance -->
|
|
454
|
+
<div v-else class="space-y-4 text-sm">
|
|
455
|
+
<div class="grid grid-cols-2 gap-3">
|
|
456
|
+
<div class="rounded-md border border-[var(--ui-border)] p-3">
|
|
457
|
+
<p class="arka-eyebrow">
|
|
458
|
+
complexity
|
|
459
|
+
</p>
|
|
460
|
+
<p class="mt-1">
|
|
461
|
+
<span class="arka-data text-lg">{{ plan.complexity.score }}</span>
|
|
462
|
+
<span class="ml-2 text-xs text-muted">{{ plan.complexity.tier }}</span>
|
|
463
|
+
</p>
|
|
464
|
+
</div>
|
|
465
|
+
<div class="rounded-md border border-[var(--ui-border)] p-3">
|
|
466
|
+
<p class="arka-eyebrow">
|
|
467
|
+
critic confidence
|
|
468
|
+
</p>
|
|
469
|
+
<p class="arka-data mt-1 text-lg">
|
|
470
|
+
{{ (plan.critic.confidence ?? 0).toFixed(2) }}
|
|
471
|
+
</p>
|
|
472
|
+
</div>
|
|
473
|
+
</div>
|
|
474
|
+
<div v-if="plan.critic.risks.length">
|
|
475
|
+
<p class="arka-eyebrow mb-1.5">
|
|
476
|
+
risks identified
|
|
477
|
+
</p>
|
|
478
|
+
<ul class="space-y-1 text-xs text-muted">
|
|
479
|
+
<li v-for="(risk, i) in plan.critic.risks" :key="i" class="flex flex-col gap-0.5">
|
|
480
|
+
<span>
|
|
481
|
+
<span class="mr-1.5 uppercase">{{ risk.severity || 'risk' }}</span>
|
|
482
|
+
{{ risk.risk || '—' }}
|
|
483
|
+
</span>
|
|
484
|
+
<span v-if="risk.mitigation" class="pl-1 italic">
|
|
485
|
+
→ {{ risk.mitigation }}
|
|
486
|
+
</span>
|
|
487
|
+
</li>
|
|
488
|
+
</ul>
|
|
489
|
+
</div>
|
|
490
|
+
<div>
|
|
491
|
+
<p class="arka-eyebrow mb-1.5">
|
|
492
|
+
governance
|
|
493
|
+
</p>
|
|
494
|
+
<p class="text-xs text-muted">
|
|
495
|
+
constitution: {{ plan.governance.constitution_check }}
|
|
496
|
+
· quality gate:
|
|
497
|
+
{{ plan.governance.quality_gate_required ? 'required' : 'not required' }}
|
|
498
|
+
· path: {{ plan.execution_path.type }}
|
|
499
|
+
<template v-if="plan.execution_path.target">
|
|
500
|
+
→ {{ plan.execution_path.target }}
|
|
501
|
+
</template>
|
|
502
|
+
</p>
|
|
503
|
+
<p
|
|
504
|
+
v-if="plan.governance.violations.length"
|
|
505
|
+
class="mt-1 text-xs text-error"
|
|
506
|
+
>
|
|
507
|
+
violations: {{ plan.governance.violations.join('; ') }}
|
|
508
|
+
</p>
|
|
509
|
+
</div>
|
|
510
|
+
</div>
|
|
511
|
+
</div>
|
|
512
|
+
|
|
513
|
+
<!-- The Decision Rail: static line, stations, real trail.
|
|
514
|
+
Only the current station pulses. -->
|
|
515
|
+
<aside aria-label="Plan lifecycle and decision">
|
|
516
|
+
<ol class="relative ml-2 border-l border-[var(--ui-border)] pl-5">
|
|
517
|
+
<li
|
|
518
|
+
v-for="station in railStations"
|
|
519
|
+
:key="station.stage"
|
|
520
|
+
class="relative pb-5 last:pb-0"
|
|
521
|
+
>
|
|
522
|
+
<span
|
|
523
|
+
class="absolute -left-[27px] top-0.5 flex size-3 items-center justify-center"
|
|
524
|
+
aria-hidden="true"
|
|
525
|
+
>
|
|
526
|
+
<span v-if="station.current" class="arka-live-dot" />
|
|
527
|
+
<span
|
|
528
|
+
v-else
|
|
529
|
+
class="size-1.5 rounded-full"
|
|
530
|
+
:class="station.reached
|
|
531
|
+
? 'bg-[var(--ui-text-muted)]'
|
|
532
|
+
: 'bg-[var(--ui-border)]'"
|
|
533
|
+
/>
|
|
534
|
+
</span>
|
|
535
|
+
<p
|
|
536
|
+
class="arka-eyebrow"
|
|
537
|
+
:class="station.current
|
|
538
|
+
? 'text-[var(--ui-text)]'
|
|
539
|
+
: station.reached ? '' : 'opacity-40'"
|
|
540
|
+
>
|
|
541
|
+
{{ station.stage }}
|
|
542
|
+
</p>
|
|
543
|
+
<p v-if="station.detail" class="arka-data mt-0.5 text-[10px] text-muted">
|
|
544
|
+
{{ station.detail }}
|
|
545
|
+
</p>
|
|
546
|
+
<p
|
|
547
|
+
v-if="station.note"
|
|
548
|
+
class="mt-1 border-l-2 border-[var(--ui-border)] pl-2 text-[11px] italic text-muted"
|
|
549
|
+
>
|
|
550
|
+
{{ station.note }}
|
|
551
|
+
</p>
|
|
552
|
+
</li>
|
|
553
|
+
</ol>
|
|
554
|
+
|
|
555
|
+
<!-- negative terminal leaves the line (deviation IS
|
|
556
|
+
the meaning) -->
|
|
557
|
+
<div
|
|
558
|
+
v-if="negativeTerminal"
|
|
559
|
+
class="ml-6 mt-3 rounded-md border border-dashed border-[var(--ui-border)] p-2.5"
|
|
560
|
+
>
|
|
561
|
+
<p class="arka-eyebrow capitalize text-muted">
|
|
562
|
+
{{ negativeTerminal.stage }}
|
|
563
|
+
</p>
|
|
564
|
+
<p
|
|
565
|
+
v-if="negativeTerminal.detail"
|
|
566
|
+
class="arka-data mt-0.5 text-[10px] text-muted"
|
|
567
|
+
>
|
|
568
|
+
{{ negativeTerminal.detail }}
|
|
569
|
+
</p>
|
|
570
|
+
<p
|
|
571
|
+
v-if="negativeTerminal.note"
|
|
572
|
+
class="mt-1 text-[11px] italic text-muted"
|
|
573
|
+
>
|
|
574
|
+
{{ negativeTerminal.note }}
|
|
575
|
+
</p>
|
|
576
|
+
</div>
|
|
577
|
+
|
|
578
|
+
<!-- decision zone: anchored at the rail, one primary CTA -->
|
|
579
|
+
<div v-if="decidable" class="mt-5 space-y-2.5">
|
|
580
|
+
<UTextarea
|
|
581
|
+
v-model="note"
|
|
582
|
+
placeholder="Decision note (lands on the record)"
|
|
583
|
+
:rows="3"
|
|
584
|
+
class="w-full"
|
|
585
|
+
aria-label="Decision note"
|
|
586
|
+
/>
|
|
587
|
+
<div class="flex flex-col gap-2">
|
|
588
|
+
<UButton
|
|
589
|
+
label="Approve plan"
|
|
590
|
+
color="primary"
|
|
591
|
+
icon="i-lucide-check"
|
|
592
|
+
block
|
|
593
|
+
:loading="deciding"
|
|
594
|
+
@click="decide('approve')"
|
|
595
|
+
/>
|
|
596
|
+
<UButton
|
|
597
|
+
label="Reject"
|
|
598
|
+
color="neutral"
|
|
599
|
+
variant="outline"
|
|
600
|
+
icon="i-lucide-x"
|
|
601
|
+
block
|
|
602
|
+
:disabled="deciding"
|
|
603
|
+
@click="decide('reject')"
|
|
604
|
+
/>
|
|
605
|
+
</div>
|
|
606
|
+
</div>
|
|
607
|
+
</aside>
|
|
608
|
+
</div>
|
|
609
|
+
</ArkaGlowCard>
|
|
610
|
+
|
|
611
|
+
<div
|
|
612
|
+
v-else
|
|
613
|
+
class="flex h-full min-h-48 items-center justify-center rounded-md border border-dashed border-[var(--ui-border)]"
|
|
614
|
+
>
|
|
615
|
+
<p v-if="detailStatus === 'pending'" class="text-sm text-muted" role="status">
|
|
616
|
+
<UIcon name="i-lucide-loader-2" class="mr-1 inline size-4 animate-spin" />
|
|
617
|
+
loading plan…
|
|
618
|
+
</p>
|
|
619
|
+
<p v-else class="max-w-56 text-center text-sm text-muted">
|
|
620
|
+
Select a plan to review — the queue stays in sight while you read.
|
|
621
|
+
</p>
|
|
622
|
+
</div>
|
|
623
|
+
</div>
|
|
624
|
+
</div>
|
|
625
|
+
</ArkaSection>
|
|
626
|
+
</div>
|
|
627
|
+
</DashboardState>
|
|
628
|
+
</template>
|
|
629
|
+
</UDashboardPanel>
|
|
630
|
+
</template>
|
|
@@ -8,8 +8,9 @@ allowed-tools: [Read, Write, Edit, Bash, Grep, Glob, Agent, WebFetch, WebSearch]
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
<!-- arka:kb-first-prefix begin -->
|
|
11
|
-
> **KB-first:** query `mcp__obsidian__search_notes` and
|
|
12
|
-
> `[[wikilinks]]`
|
|
11
|
+
> **KB-first:** query `mcp__obsidian__search_notes` (and
|
|
12
|
+
> `mcp__graphify__query_graph` when configured) and cite `[[wikilinks]]`
|
|
13
|
+
> or graph nodes — or declare the gap — BEFORE any external research.
|
|
13
14
|
> Full doctrine: `arka/SKILL.md` (KB-First Research).
|
|
14
15
|
<!-- arka:kb-first-prefix end -->
|
|
15
16
|
|
|
@@ -12,8 +12,9 @@ allowed-tools: [Read, Write, Edit, Bash, Grep, Glob, Agent, WebFetch, WebSearch]
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
<!-- arka:kb-first-prefix begin -->
|
|
15
|
-
> **KB-first:** query `mcp__obsidian__search_notes` and
|
|
16
|
-
> `[[wikilinks]]`
|
|
15
|
+
> **KB-first:** query `mcp__obsidian__search_notes` (and
|
|
16
|
+
> `mcp__graphify__query_graph` when configured) and cite `[[wikilinks]]`
|
|
17
|
+
> or graph nodes — or declare the gap — BEFORE any external research.
|
|
17
18
|
> Full doctrine: `arka/SKILL.md` (KB-First Research).
|
|
18
19
|
<!-- arka:kb-first-prefix end -->
|
|
19
20
|
|
|
@@ -12,8 +12,9 @@ allowed-tools: [Read, Write, Edit, Bash, Grep, Glob, Agent, WebFetch, WebSearch]
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
<!-- arka:kb-first-prefix begin -->
|
|
15
|
-
> **KB-first:** query `mcp__obsidian__search_notes` and
|
|
16
|
-
> `[[wikilinks]]`
|
|
15
|
+
> **KB-first:** query `mcp__obsidian__search_notes` (and
|
|
16
|
+
> `mcp__graphify__query_graph` when configured) and cite `[[wikilinks]]`
|
|
17
|
+
> or graph nodes — or declare the gap — BEFORE any external research.
|
|
17
18
|
> Full doctrine: `arka/SKILL.md` (KB-First Research).
|
|
18
19
|
<!-- arka:kb-first-prefix end -->
|
|
19
20
|
|
|
@@ -14,8 +14,9 @@ allowed-tools: [Read, Write, Edit, Bash, Grep, Glob, Agent, WebFetch, WebSearch]
|
|
|
14
14
|
---
|
|
15
15
|
|
|
16
16
|
<!-- arka:kb-first-prefix begin -->
|
|
17
|
-
> **KB-first:** query `mcp__obsidian__search_notes` and
|
|
18
|
-
> `[[wikilinks]]`
|
|
17
|
+
> **KB-first:** query `mcp__obsidian__search_notes` (and
|
|
18
|
+
> `mcp__graphify__query_graph` when configured) and cite `[[wikilinks]]`
|
|
19
|
+
> or graph nodes — or declare the gap — BEFORE any external research.
|
|
19
20
|
> Full doctrine: `arka/SKILL.md` (KB-First Research).
|
|
20
21
|
<!-- arka:kb-first-prefix end -->
|
|
21
22
|
|