@skillkit/tui 1.5.0 → 1.6.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/dist/index.js CHANGED
@@ -2,8 +2,8 @@
2
2
  import { render } from "ink";
3
3
 
4
4
  // src/App.tsx
5
- import { useState as useState19 } from "react";
6
- import { Box as Box17, Text as Text17, useInput as useInput15, useApp, useStdout } from "ink";
5
+ import { useState as useState21 } from "react";
6
+ import { Box as Box19, Text as Text19, useInput as useInput17, useApp, useStdout } from "ink";
7
7
 
8
8
  // src/components/Sidebar.tsx
9
9
  import { Box, Text } from "ink";
@@ -58,6 +58,9 @@ var NAV = [
58
58
  // Collaboration
59
59
  { id: "team", label: "Team", key: "a" },
60
60
  { id: "plugins", label: "Plugins", key: "p" },
61
+ // Methodology
62
+ { id: "methodology", label: "Methodology", key: "o" },
63
+ { id: "plan", label: "Plans", key: "n" },
61
64
  // Tools
62
65
  { id: "recommend", label: "Recommend", key: "r" },
63
66
  { id: "translate", label: "Translate", key: "t" },
@@ -86,12 +89,17 @@ function Sidebar({ screen }) {
86
89
  item.label
87
90
  ] }, item.id)),
88
91
  /* @__PURE__ */ jsx(Text, { children: " " }),
89
- NAV.slice(8, 12).map((item) => /* @__PURE__ */ jsxs(Text, { inverse: screen === item.id, children: [
92
+ NAV.slice(8, 10).map((item) => /* @__PURE__ */ jsxs(Text, { inverse: screen === item.id, children: [
90
93
  screen === item.id ? symbols.bullet : " ",
91
94
  item.label
92
95
  ] }, item.id)),
93
96
  /* @__PURE__ */ jsx(Text, { children: " " }),
94
- NAV.slice(12).map((item) => /* @__PURE__ */ jsxs(Text, { inverse: screen === item.id, children: [
97
+ NAV.slice(10, 14).map((item) => /* @__PURE__ */ jsxs(Text, { inverse: screen === item.id, children: [
98
+ screen === item.id ? symbols.bullet : " ",
99
+ item.label
100
+ ] }, item.id)),
101
+ /* @__PURE__ */ jsx(Text, { children: " " }),
102
+ NAV.slice(14).map((item) => /* @__PURE__ */ jsxs(Text, { inverse: screen === item.id, children: [
95
103
  screen === item.id ? symbols.bullet : " ",
96
104
  item.label
97
105
  ] }, item.id)),
@@ -2777,9 +2785,9 @@ function Plugins({ rows = 24 }) {
2777
2785
  setError(null);
2778
2786
  try {
2779
2787
  const { createPluginManager, loadPluginsFromDirectory } = await import("@skillkit/core");
2780
- const { join: join6 } = await import("path");
2788
+ const { join: join7 } = await import("path");
2781
2789
  const manager = createPluginManager(process.cwd());
2782
- const pluginsDir = join6(process.cwd(), ".skillkit", "plugins");
2790
+ const pluginsDir = join7(process.cwd(), ".skillkit", "plugins");
2783
2791
  try {
2784
2792
  const loadedPlugins = await loadPluginsFromDirectory(pluginsDir);
2785
2793
  for (const plugin of loadedPlugins) {
@@ -2817,9 +2825,9 @@ function Plugins({ rows = 24 }) {
2817
2825
  setMessage(null);
2818
2826
  try {
2819
2827
  const { createPluginManager, loadPluginsFromDirectory } = await import("@skillkit/core");
2820
- const { join: join6 } = await import("path");
2828
+ const { join: join7 } = await import("path");
2821
2829
  const manager = createPluginManager(process.cwd());
2822
- const pluginsDir = join6(process.cwd(), ".skillkit", "plugins");
2830
+ const pluginsDir = join7(process.cwd(), ".skillkit", "plugins");
2823
2831
  try {
2824
2832
  const loadedPlugins = await loadPluginsFromDirectory(pluginsDir);
2825
2833
  for (const plugin of loadedPlugins) {
@@ -2934,10 +2942,456 @@ function Plugins({ rows = 24 }) {
2934
2942
  ] });
2935
2943
  }
2936
2944
 
2945
+ // src/screens/Methodology.tsx
2946
+ import { useState as useState19, useEffect as useEffect16, useMemo } from "react";
2947
+ import { Box as Box17, Text as Text17, useInput as useInput15 } from "ink";
2948
+ import {
2949
+ MethodologyManager
2950
+ } from "@skillkit/core";
2951
+ import { Fragment as Fragment2, jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
2952
+ function Methodology({ rows = 24 }) {
2953
+ const [packs, setPacks] = useState19([]);
2954
+ const [selectedPack, setSelectedPack] = useState19(null);
2955
+ const [skills, setSkills] = useState19([]);
2956
+ const [loading, setLoading] = useState19(true);
2957
+ const [view, setView] = useState19("packs");
2958
+ const [sel, setSel] = useState19(0);
2959
+ const [error, setError] = useState19(null);
2960
+ const [message, setMessage] = useState19(null);
2961
+ const manager = useMemo(() => new MethodologyManager({
2962
+ projectPath: process.cwd()
2963
+ }), []);
2964
+ const maxVisible = Math.max(5, rows - 10);
2965
+ useEffect16(() => {
2966
+ loadPacks();
2967
+ }, []);
2968
+ const loadPacks = async () => {
2969
+ setLoading(true);
2970
+ setError(null);
2971
+ try {
2972
+ const loadedPacks = await manager.listAvailablePacks();
2973
+ setPacks(loadedPacks);
2974
+ } catch (e) {
2975
+ setError(e instanceof Error ? e.message : "Failed to load methodology packs");
2976
+ }
2977
+ setLoading(false);
2978
+ };
2979
+ const loadSkills = async (pack) => {
2980
+ setLoading(true);
2981
+ setError(null);
2982
+ try {
2983
+ const loader = manager.getLoader();
2984
+ const loadedSkills = await loader.loadPackSkills(pack.name);
2985
+ setSkills(loadedSkills);
2986
+ setSelectedPack(pack);
2987
+ setView("skills");
2988
+ setSel(0);
2989
+ } catch (e) {
2990
+ setError(e instanceof Error ? e.message : "Failed to load skills");
2991
+ }
2992
+ setLoading(false);
2993
+ };
2994
+ const installPack = async (pack) => {
2995
+ setLoading(true);
2996
+ setMessage(null);
2997
+ try {
2998
+ await manager.installPack(pack.name);
2999
+ setMessage(`Installed ${pack.name} methodology pack`);
3000
+ await loadPacks();
3001
+ } catch (e) {
3002
+ setError(e instanceof Error ? e.message : "Failed to install pack");
3003
+ }
3004
+ setLoading(false);
3005
+ };
3006
+ const items = view === "packs" ? packs : skills;
3007
+ const start = Math.max(0, Math.min(sel - Math.floor(maxVisible / 2), items.length - maxVisible));
3008
+ const visible = items.slice(start, start + maxVisible);
3009
+ useInput15((input, key) => {
3010
+ if (loading) return;
3011
+ if (key.upArrow) setSel((i) => Math.max(0, i - 1));
3012
+ else if (key.downArrow) setSel((i) => Math.min(items.length - 1, i + 1));
3013
+ else if (input === "r") {
3014
+ if (view === "packs") loadPacks();
3015
+ else if (selectedPack) loadSkills(selectedPack);
3016
+ } else if (key.escape || input === "b") {
3017
+ if (view === "skills") {
3018
+ setView("packs");
3019
+ setSel(0);
3020
+ setSelectedPack(null);
3021
+ }
3022
+ } else if (key.return) {
3023
+ if (view === "packs" && packs[sel]) {
3024
+ loadSkills(packs[sel]);
3025
+ }
3026
+ } else if (input === "i" && view === "packs" && packs[sel]) {
3027
+ installPack(packs[sel]);
3028
+ }
3029
+ });
3030
+ const renderPackItem = (pack, idx) => {
3031
+ const isSel = idx === sel;
3032
+ return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", children: [
3033
+ /* @__PURE__ */ jsxs17(Text17, { inverse: isSel, children: [
3034
+ isSel ? symbols.pointer : " ",
3035
+ " ",
3036
+ pack.name,
3037
+ " ",
3038
+ /* @__PURE__ */ jsxs17(Text17, { dimColor: true, children: [
3039
+ "v",
3040
+ pack.version
3041
+ ] })
3042
+ ] }),
3043
+ isSel && /* @__PURE__ */ jsxs17(Fragment2, { children: [
3044
+ /* @__PURE__ */ jsxs17(Text17, { dimColor: true, children: [
3045
+ " ",
3046
+ pack.description
3047
+ ] }),
3048
+ /* @__PURE__ */ jsxs17(Text17, { dimColor: true, children: [
3049
+ " ",
3050
+ pack.skills.length,
3051
+ " skill(s) | Tags: ",
3052
+ pack.tags?.join(", ") || "none"
3053
+ ] })
3054
+ ] })
3055
+ ] }, pack.name);
3056
+ };
3057
+ const renderSkillItem = (skill, idx) => {
3058
+ const isSel = idx === sel;
3059
+ return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", children: [
3060
+ /* @__PURE__ */ jsxs17(Text17, { inverse: isSel, children: [
3061
+ isSel ? symbols.pointer : " ",
3062
+ " ",
3063
+ skill.name
3064
+ ] }),
3065
+ isSel && skill.description && /* @__PURE__ */ jsxs17(Text17, { dimColor: true, children: [
3066
+ " ",
3067
+ skill.description
3068
+ ] }),
3069
+ isSel && skill.tags && /* @__PURE__ */ jsxs17(Text17, { dimColor: true, children: [
3070
+ " Tags: ",
3071
+ skill.tags.join(", ")
3072
+ ] })
3073
+ ] }, skill.name);
3074
+ };
3075
+ return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", children: [
3076
+ /* @__PURE__ */ jsx17(Text17, { bold: true, color: colors.primary, children: view === "packs" ? "METHODOLOGY PACKS" : `${selectedPack?.name.toUpperCase()} SKILLS` }),
3077
+ /* @__PURE__ */ jsx17(Text17, { dimColor: true, children: view === "packs" ? `${packs.length} pack(s) available` : `${skills.length} skill(s) in pack` }),
3078
+ loading && /* @__PURE__ */ jsx17(Text17, { color: "yellow", children: "Loading..." }),
3079
+ error && /* @__PURE__ */ jsxs17(Text17, { color: "red", children: [
3080
+ symbols.error,
3081
+ " ",
3082
+ error
3083
+ ] }),
3084
+ message && /* @__PURE__ */ jsxs17(Text17, { color: "green", children: [
3085
+ symbols.success,
3086
+ " ",
3087
+ message
3088
+ ] }),
3089
+ !loading && items.length === 0 && /* @__PURE__ */ jsx17(Box17, { marginTop: 1, children: /* @__PURE__ */ jsxs17(Text17, { dimColor: true, children: [
3090
+ "No ",
3091
+ view === "packs" ? "methodology packs" : "skills",
3092
+ " found."
3093
+ ] }) }),
3094
+ !loading && items.length > 0 && /* @__PURE__ */ jsxs17(Box17, { marginTop: 1, flexDirection: "column", children: [
3095
+ start > 0 && /* @__PURE__ */ jsxs17(Text17, { dimColor: true, children: [
3096
+ " ",
3097
+ symbols.arrowUp,
3098
+ " ",
3099
+ start,
3100
+ " more"
3101
+ ] }),
3102
+ view === "packs" ? visible.map((pack, i) => renderPackItem(pack, start + i)) : visible.map((skill, i) => renderSkillItem(skill, start + i)),
3103
+ start + maxVisible < items.length && /* @__PURE__ */ jsxs17(Text17, { dimColor: true, children: [
3104
+ " ",
3105
+ symbols.arrowDown,
3106
+ " ",
3107
+ items.length - start - maxVisible,
3108
+ " more"
3109
+ ] })
3110
+ ] }),
3111
+ /* @__PURE__ */ jsx17(Box17, { marginTop: 1, flexDirection: "column", children: view === "packs" ? /* @__PURE__ */ jsx17(Text17, { dimColor: true, children: "Enter=view skills i=install r=refresh q=quit" }) : /* @__PURE__ */ jsx17(Text17, { dimColor: true, children: "b/Esc=back r=refresh q=quit" }) })
3112
+ ] });
3113
+ }
3114
+
3115
+ // src/screens/Plan.tsx
3116
+ import { useState as useState20, useEffect as useEffect17, useMemo as useMemo2 } from "react";
3117
+ import { Box as Box18, Text as Text18, useInput as useInput16 } from "ink";
3118
+ import {
3119
+ PlanParser,
3120
+ PlanValidator,
3121
+ PlanExecutor
3122
+ } from "@skillkit/core";
3123
+ import * as fs from "fs";
3124
+ import * as path from "path";
3125
+ import { Fragment as Fragment3, jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
3126
+ function Plan({ rows = 24 }) {
3127
+ const [planFiles, setPlanFiles] = useState20([]);
3128
+ const [selectedPlan, setSelectedPlan] = useState20(null);
3129
+ const [selectedTask, setSelectedTask] = useState20(null);
3130
+ const [loading, setLoading] = useState20(true);
3131
+ const [view, setView] = useState20("plans");
3132
+ const [sel, setSel] = useState20(0);
3133
+ const [error, setError] = useState20(null);
3134
+ const [executing, setExecuting] = useState20(false);
3135
+ const [message, setMessage] = useState20(null);
3136
+ const parser = useMemo2(() => new PlanParser(), []);
3137
+ const validator = useMemo2(() => new PlanValidator(), []);
3138
+ const maxVisible = Math.max(5, rows - 10);
3139
+ useEffect17(() => {
3140
+ loadPlans();
3141
+ }, []);
3142
+ const loadPlans = async () => {
3143
+ setLoading(true);
3144
+ setError(null);
3145
+ try {
3146
+ const cwd = process.cwd();
3147
+ const files = [];
3148
+ const searchPaths = [
3149
+ cwd,
3150
+ path.join(cwd, "plans"),
3151
+ path.join(cwd, ".skillkit", "plans")
3152
+ ];
3153
+ for (const searchPath of searchPaths) {
3154
+ if (fs.existsSync(searchPath)) {
3155
+ const entries = fs.readdirSync(searchPath, { withFileTypes: true });
3156
+ for (const entry of entries) {
3157
+ if (entry.isFile() && (entry.name.endsWith(".plan.md") || entry.name.endsWith("-plan.md"))) {
3158
+ const filePath = path.join(searchPath, entry.name);
3159
+ const content = fs.readFileSync(filePath, "utf-8");
3160
+ try {
3161
+ const plan = parser.parse(content);
3162
+ const validation = validator.validate(plan);
3163
+ const errorIssue = validation.issues.find((i) => i.type === "error");
3164
+ files.push({
3165
+ name: entry.name,
3166
+ path: filePath,
3167
+ plan,
3168
+ valid: validation.valid,
3169
+ error: errorIssue?.message
3170
+ });
3171
+ } catch {
3172
+ files.push({
3173
+ name: entry.name,
3174
+ path: filePath,
3175
+ valid: false,
3176
+ error: "Failed to parse plan"
3177
+ });
3178
+ }
3179
+ }
3180
+ }
3181
+ }
3182
+ }
3183
+ setPlanFiles(files);
3184
+ } catch (e) {
3185
+ setError(e instanceof Error ? e.message : "Failed to load plans");
3186
+ }
3187
+ setLoading(false);
3188
+ };
3189
+ const selectPlan = (planFile) => {
3190
+ if (planFile.plan) {
3191
+ setSelectedPlan(planFile);
3192
+ setView("tasks");
3193
+ setSel(0);
3194
+ }
3195
+ };
3196
+ const selectTask = (task) => {
3197
+ setSelectedTask(task);
3198
+ setView("steps");
3199
+ setSel(0);
3200
+ };
3201
+ const executePlan = async (planFile) => {
3202
+ if (!planFile.plan) return;
3203
+ setExecuting(true);
3204
+ setMessage(null);
3205
+ try {
3206
+ const executor = new PlanExecutor();
3207
+ await executor.execute(planFile.plan, { dryRun: true });
3208
+ setMessage(`Executed plan: ${planFile.plan.name} (dry run)`);
3209
+ } catch (e) {
3210
+ setError(e instanceof Error ? e.message : "Failed to execute plan");
3211
+ }
3212
+ setExecuting(false);
3213
+ };
3214
+ const getItems = () => {
3215
+ if (view === "plans") return planFiles;
3216
+ if (view === "tasks" && selectedPlan?.plan) return selectedPlan.plan.tasks;
3217
+ if (view === "steps" && selectedTask) return selectedTask.steps;
3218
+ return [];
3219
+ };
3220
+ const items = getItems();
3221
+ const start = Math.max(0, Math.min(sel - Math.floor(maxVisible / 2), items.length - maxVisible));
3222
+ const visible = items.slice(start, start + maxVisible);
3223
+ useInput16((input, key) => {
3224
+ if (loading || executing) return;
3225
+ if (key.upArrow) setSel((i) => Math.max(0, i - 1));
3226
+ else if (key.downArrow) setSel((i) => Math.min(items.length - 1, i + 1));
3227
+ else if (input === "r") loadPlans();
3228
+ else if (key.escape || input === "b") {
3229
+ if (view === "steps") {
3230
+ setView("tasks");
3231
+ setSelectedTask(null);
3232
+ setSel(0);
3233
+ } else if (view === "tasks") {
3234
+ setView("plans");
3235
+ setSelectedPlan(null);
3236
+ setSel(0);
3237
+ }
3238
+ } else if (key.return) {
3239
+ if (view === "plans" && planFiles[sel]) {
3240
+ selectPlan(planFiles[sel]);
3241
+ } else if (view === "tasks" && selectedPlan?.plan?.tasks[sel]) {
3242
+ selectTask(selectedPlan.plan.tasks[sel]);
3243
+ }
3244
+ } else if (input === "x" && view === "plans" && planFiles[sel]?.plan) {
3245
+ executePlan(planFiles[sel]);
3246
+ }
3247
+ });
3248
+ const renderPlanItem = (planFile, idx) => {
3249
+ const isSel = idx === sel;
3250
+ const statusIcon = planFile.valid ? symbols.success : symbols.error;
3251
+ const statusColor = planFile.valid ? "green" : "red";
3252
+ return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", children: [
3253
+ /* @__PURE__ */ jsxs18(Text18, { inverse: isSel, children: [
3254
+ isSel ? symbols.pointer : " ",
3255
+ " ",
3256
+ /* @__PURE__ */ jsx18(Text18, { color: statusColor, children: statusIcon }),
3257
+ " ",
3258
+ planFile.name
3259
+ ] }),
3260
+ isSel && planFile.plan && /* @__PURE__ */ jsxs18(Fragment3, { children: [
3261
+ /* @__PURE__ */ jsxs18(Text18, { dimColor: true, children: [
3262
+ " ",
3263
+ planFile.plan.goal
3264
+ ] }),
3265
+ /* @__PURE__ */ jsxs18(Text18, { dimColor: true, children: [
3266
+ " ",
3267
+ planFile.plan.tasks.length,
3268
+ " task(s) | ",
3269
+ planFile.plan.techStack?.join(", ") || "No stack"
3270
+ ] })
3271
+ ] }),
3272
+ isSel && planFile.error && /* @__PURE__ */ jsxs18(Text18, { color: "red", children: [
3273
+ " ",
3274
+ planFile.error
3275
+ ] })
3276
+ ] }, planFile.path);
3277
+ };
3278
+ const renderTaskItem = (task, idx) => {
3279
+ const isSel = idx === sel;
3280
+ return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", children: [
3281
+ /* @__PURE__ */ jsxs18(Text18, { inverse: isSel, children: [
3282
+ isSel ? symbols.pointer : " ",
3283
+ " [",
3284
+ task.id,
3285
+ "] ",
3286
+ task.name
3287
+ ] }),
3288
+ isSel && /* @__PURE__ */ jsxs18(Fragment3, { children: [
3289
+ /* @__PURE__ */ jsxs18(Text18, { dimColor: true, children: [
3290
+ " ",
3291
+ task.steps.length,
3292
+ " step(s)"
3293
+ ] }),
3294
+ task.files?.create && /* @__PURE__ */ jsxs18(Text18, { dimColor: true, children: [
3295
+ " Create: ",
3296
+ task.files.create.join(", ")
3297
+ ] }),
3298
+ task.files?.modify && /* @__PURE__ */ jsxs18(Text18, { dimColor: true, children: [
3299
+ " Modify: ",
3300
+ task.files.modify.join(", ")
3301
+ ] }),
3302
+ task.files?.test && /* @__PURE__ */ jsxs18(Text18, { dimColor: true, children: [
3303
+ " Test: ",
3304
+ task.files.test.join(", ")
3305
+ ] })
3306
+ ] })
3307
+ ] }, task.id);
3308
+ };
3309
+ const renderStepItem = (step, idx) => {
3310
+ const isSel = idx === sel;
3311
+ const typeColors = {
3312
+ test: "yellow",
3313
+ verify: "cyan",
3314
+ implement: "green",
3315
+ commit: "magenta"
3316
+ };
3317
+ return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", children: [
3318
+ /* @__PURE__ */ jsxs18(Text18, { inverse: isSel, children: [
3319
+ isSel ? symbols.pointer : " ",
3320
+ " ",
3321
+ /* @__PURE__ */ jsxs18(Text18, { color: typeColors[step.type] || "white", children: [
3322
+ "[",
3323
+ step.type,
3324
+ "]"
3325
+ ] }),
3326
+ " Step ",
3327
+ step.number
3328
+ ] }),
3329
+ isSel && /* @__PURE__ */ jsxs18(Text18, { dimColor: true, children: [
3330
+ " ",
3331
+ step.description
3332
+ ] })
3333
+ ] }, step.number);
3334
+ };
3335
+ const getTitle = () => {
3336
+ if (view === "plans") return "PLANS";
3337
+ if (view === "tasks") return `TASKS: ${selectedPlan?.plan?.name || ""}`;
3338
+ if (view === "steps") return `STEPS: Task ${selectedTask?.id}`;
3339
+ return "PLANS";
3340
+ };
3341
+ return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", children: [
3342
+ /* @__PURE__ */ jsx18(Text18, { bold: true, color: colors.primary, children: getTitle() }),
3343
+ /* @__PURE__ */ jsxs18(Text18, { dimColor: true, children: [
3344
+ view === "plans" && `${planFiles.length} plan(s) found`,
3345
+ view === "tasks" && selectedPlan?.plan && `${selectedPlan.plan.tasks.length} task(s)`,
3346
+ view === "steps" && selectedTask && `${selectedTask.steps.length} step(s)`
3347
+ ] }),
3348
+ loading && /* @__PURE__ */ jsx18(Text18, { color: "yellow", children: "Loading plans..." }),
3349
+ executing && /* @__PURE__ */ jsx18(Text18, { color: "yellow", children: "Executing plan..." }),
3350
+ error && /* @__PURE__ */ jsxs18(Text18, { color: "red", children: [
3351
+ symbols.error,
3352
+ " ",
3353
+ error
3354
+ ] }),
3355
+ message && /* @__PURE__ */ jsxs18(Text18, { color: "green", children: [
3356
+ symbols.success,
3357
+ " ",
3358
+ message
3359
+ ] }),
3360
+ !loading && !executing && items.length === 0 && /* @__PURE__ */ jsxs18(Box18, { marginTop: 1, flexDirection: "column", children: [
3361
+ /* @__PURE__ */ jsxs18(Text18, { dimColor: true, children: [
3362
+ "No ",
3363
+ view,
3364
+ " found."
3365
+ ] }),
3366
+ view === "plans" && /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: "Create a plan file: *.plan.md or *-plan.md" })
3367
+ ] }),
3368
+ !loading && !executing && items.length > 0 && /* @__PURE__ */ jsxs18(Box18, { marginTop: 1, flexDirection: "column", children: [
3369
+ start > 0 && /* @__PURE__ */ jsxs18(Text18, { dimColor: true, children: [
3370
+ " \u2191 ",
3371
+ start,
3372
+ " more"
3373
+ ] }),
3374
+ view === "plans" && visible.map((pf, i) => renderPlanItem(pf, start + i)),
3375
+ view === "tasks" && visible.map((t, i) => renderTaskItem(t, start + i)),
3376
+ view === "steps" && visible.map((s, i) => renderStepItem(s, start + i)),
3377
+ start + maxVisible < items.length && /* @__PURE__ */ jsxs18(Text18, { dimColor: true, children: [
3378
+ " \u2193 ",
3379
+ items.length - start - maxVisible,
3380
+ " more"
3381
+ ] })
3382
+ ] }),
3383
+ /* @__PURE__ */ jsxs18(Box18, { marginTop: 1, children: [
3384
+ view === "plans" && /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: "Enter=view tasks x=execute (dry-run) r=refresh q=quit" }),
3385
+ view === "tasks" && /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: "Enter=view steps b/Esc=back q=quit" }),
3386
+ view === "steps" && /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: "b/Esc=back q=quit" })
3387
+ ] })
3388
+ ] });
3389
+ }
3390
+
2937
3391
  // src/App.tsx
2938
- import { jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
3392
+ import { jsx as jsx19, jsxs as jsxs19 } from "react/jsx-runtime";
2939
3393
  function App() {
2940
- const [screen, setScreen] = useState19("home");
3394
+ const [screen, setScreen] = useState21("home");
2941
3395
  const { exit } = useApp();
2942
3396
  const { stdout } = useStdout();
2943
3397
  const cols = stdout?.columns || 80;
@@ -2958,9 +3412,11 @@ function App() {
2958
3412
  s: "sync",
2959
3413
  a: "team",
2960
3414
  p: "plugins",
3415
+ o: "methodology",
3416
+ n: "plan",
2961
3417
  ",": "settings"
2962
3418
  };
2963
- useInput15((input, key) => {
3419
+ useInput17((input, key) => {
2964
3420
  if (input === "q") {
2965
3421
  exit();
2966
3422
  return;
@@ -2977,67 +3433,71 @@ function App() {
2977
3433
  const renderScreen = () => {
2978
3434
  switch (screen) {
2979
3435
  case "home":
2980
- return /* @__PURE__ */ jsx17(Home, { onNavigate: setScreen, cols, rows });
3436
+ return /* @__PURE__ */ jsx19(Home, { onNavigate: setScreen, cols, rows });
2981
3437
  case "browse":
2982
- return /* @__PURE__ */ jsx17(Browse, { cols, rows });
3438
+ return /* @__PURE__ */ jsx19(Browse, { cols, rows });
2983
3439
  case "installed":
2984
- return /* @__PURE__ */ jsx17(Installed, { cols, rows });
3440
+ return /* @__PURE__ */ jsx19(Installed, { cols, rows });
2985
3441
  case "sync":
2986
- return /* @__PURE__ */ jsx17(Sync, { cols, rows });
3442
+ return /* @__PURE__ */ jsx19(Sync, { cols, rows });
2987
3443
  case "settings":
2988
- return /* @__PURE__ */ jsx17(Settings, { cols, rows });
3444
+ return /* @__PURE__ */ jsx19(Settings, { cols, rows });
2989
3445
  case "recommend":
2990
- return /* @__PURE__ */ jsx17(Recommend, { cols, rows });
3446
+ return /* @__PURE__ */ jsx19(Recommend, { cols, rows });
2991
3447
  case "translate":
2992
- return /* @__PURE__ */ jsx17(Translate, { cols, rows });
3448
+ return /* @__PURE__ */ jsx19(Translate, { cols, rows });
2993
3449
  case "context":
2994
- return /* @__PURE__ */ jsx17(Context, { cols, rows });
3450
+ return /* @__PURE__ */ jsx19(Context, { cols, rows });
2995
3451
  case "workflow":
2996
- return /* @__PURE__ */ jsx17(Workflow, { cols, rows });
3452
+ return /* @__PURE__ */ jsx19(Workflow, { cols, rows });
2997
3453
  case "execute":
2998
- return /* @__PURE__ */ jsx17(Execute, { cols, rows });
3454
+ return /* @__PURE__ */ jsx19(Execute, { cols, rows });
2999
3455
  case "history":
3000
- return /* @__PURE__ */ jsx17(History, { cols, rows });
3456
+ return /* @__PURE__ */ jsx19(History, { cols, rows });
3001
3457
  case "marketplace":
3002
- return /* @__PURE__ */ jsx17(Marketplace, { cols, rows });
3458
+ return /* @__PURE__ */ jsx19(Marketplace, { cols, rows });
3003
3459
  case "memory":
3004
- return /* @__PURE__ */ jsx17(Memory, { cols, rows });
3460
+ return /* @__PURE__ */ jsx19(Memory, { cols, rows });
3005
3461
  case "team":
3006
- return /* @__PURE__ */ jsx17(Team, { cols, rows });
3462
+ return /* @__PURE__ */ jsx19(Team, { cols, rows });
3007
3463
  case "plugins":
3008
- return /* @__PURE__ */ jsx17(Plugins, { cols, rows });
3464
+ return /* @__PURE__ */ jsx19(Plugins, { cols, rows });
3465
+ case "methodology":
3466
+ return /* @__PURE__ */ jsx19(Methodology, { cols, rows });
3467
+ case "plan":
3468
+ return /* @__PURE__ */ jsx19(Plan, { cols, rows });
3009
3469
  }
3010
3470
  };
3011
3471
  const contentHeight = rows - 2;
3012
- return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", height: rows, children: [
3013
- /* @__PURE__ */ jsxs17(Box17, { flexDirection: "row", height: contentHeight, children: [
3014
- showSidebar && /* @__PURE__ */ jsx17(Sidebar, { screen, onNavigate: setScreen }),
3015
- /* @__PURE__ */ jsx17(Box17, { flexDirection: "column", flexGrow: 1, marginLeft: 1, children: renderScreen() })
3472
+ return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", height: rows, children: [
3473
+ /* @__PURE__ */ jsxs19(Box19, { flexDirection: "row", height: contentHeight, children: [
3474
+ showSidebar && /* @__PURE__ */ jsx19(Sidebar, { screen, onNavigate: setScreen }),
3475
+ /* @__PURE__ */ jsx19(Box19, { flexDirection: "column", flexGrow: 1, marginLeft: 1, children: renderScreen() })
3016
3476
  ] }),
3017
- /* @__PURE__ */ jsx17(Box17, { children: /* @__PURE__ */ jsx17(Text17, { dimColor: true, children: "h Home m Market b Browse i Inst w Wflow x Exec a Team p Plug r Rec t Trans c Ctx e Mem s Sync , Cfg q Quit" }) })
3477
+ /* @__PURE__ */ jsx19(Box19, { children: /* @__PURE__ */ jsx19(Text19, { dimColor: true, children: "h Home m Market b Browse w Wflow x Exec a Team p Plug o Meth n Plan r Rec t Trans c Ctx e Mem i Inst s Sync q Quit" }) })
3018
3478
  ] });
3019
3479
  }
3020
3480
 
3021
3481
  // src/components/Header.tsx
3022
- import { Box as Box18, Text as Text18 } from "ink";
3023
- import { jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
3482
+ import { Box as Box20, Text as Text20 } from "ink";
3483
+ import { jsx as jsx20, jsxs as jsxs20 } from "react/jsx-runtime";
3024
3484
  function Header({ title, subtitle, count }) {
3025
- return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", marginBottom: 1, children: [
3026
- /* @__PURE__ */ jsxs18(Box18, { justifyContent: "space-between", children: [
3027
- /* @__PURE__ */ jsx18(Text18, { color: colors.primary, bold: true, children: title.toUpperCase() }),
3028
- count !== void 0 && /* @__PURE__ */ jsxs18(Text18, { color: colors.secondaryDim, children: [
3485
+ return /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", marginBottom: 1, children: [
3486
+ /* @__PURE__ */ jsxs20(Box20, { justifyContent: "space-between", children: [
3487
+ /* @__PURE__ */ jsx20(Text20, { color: colors.primary, bold: true, children: title.toUpperCase() }),
3488
+ count !== void 0 && /* @__PURE__ */ jsxs20(Text20, { color: colors.secondaryDim, children: [
3029
3489
  symbols.star,
3030
3490
  " ",
3031
3491
  count
3032
3492
  ] })
3033
3493
  ] }),
3034
- subtitle && /* @__PURE__ */ jsx18(Text18, { color: colors.secondaryDim, dimColor: true, children: subtitle })
3494
+ subtitle && /* @__PURE__ */ jsx20(Text20, { color: colors.secondaryDim, dimColor: true, children: subtitle })
3035
3495
  ] });
3036
3496
  }
3037
3497
 
3038
3498
  // src/components/SkillList.tsx
3039
- import { Box as Box19, Text as Text19 } from "ink";
3040
- import { jsx as jsx19, jsxs as jsxs19 } from "react/jsx-runtime";
3499
+ import { Box as Box21, Text as Text21 } from "ink";
3500
+ import { jsx as jsx21, jsxs as jsxs21 } from "react/jsx-runtime";
3041
3501
  function formatInstalls(count) {
3042
3502
  if (count >= 1e3) {
3043
3503
  return `${(count / 1e3).toFixed(1)}K`;
@@ -3053,13 +3513,13 @@ function SkillList({
3053
3513
  maxVisible = 10
3054
3514
  }) {
3055
3515
  if (skills.length === 0) {
3056
- return /* @__PURE__ */ jsx19(Box19, { children: /* @__PURE__ */ jsx19(Text19, { color: colors.secondaryDim, dimColor: true, children: "No skills found" }) });
3516
+ return /* @__PURE__ */ jsx21(Box21, { children: /* @__PURE__ */ jsx21(Text21, { color: colors.secondaryDim, dimColor: true, children: "No skills found" }) });
3057
3517
  }
3058
3518
  const startIndex = Math.max(0, selectedIndex - Math.floor(maxVisible / 2));
3059
3519
  const visibleSkills = skills.slice(startIndex, startIndex + maxVisible);
3060
3520
  const actualStartIndex = startIndex;
3061
- return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", children: [
3062
- showRank && /* @__PURE__ */ jsx19(Box19, { marginBottom: 1, children: /* @__PURE__ */ jsxs19(Text19, { color: colors.secondaryDim, children: [
3521
+ return /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", children: [
3522
+ showRank && /* @__PURE__ */ jsx21(Box21, { marginBottom: 1, children: /* @__PURE__ */ jsxs21(Text21, { color: colors.secondaryDim, children: [
3063
3523
  " # SKILL",
3064
3524
  showSource && " SOURCE",
3065
3525
  showInstalls && " INSTALLS"
@@ -3069,9 +3529,9 @@ function SkillList({
3069
3529
  const isSelected = realIndex === selectedIndex;
3070
3530
  const skillName = skill.name.padEnd(28).slice(0, 28);
3071
3531
  const sourceName = skill.source ? skill.source.slice(0, 25) : "";
3072
- return /* @__PURE__ */ jsxs19(Box19, { children: [
3073
- /* @__PURE__ */ jsxs19(
3074
- Text19,
3532
+ return /* @__PURE__ */ jsxs21(Box21, { children: [
3533
+ /* @__PURE__ */ jsxs21(
3534
+ Text21,
3075
3535
  {
3076
3536
  color: isSelected ? colors.primary : colors.secondary,
3077
3537
  bold: isSelected,
@@ -3084,14 +3544,14 @@ function SkillList({
3084
3544
  ]
3085
3545
  }
3086
3546
  ),
3087
- showSource && /* @__PURE__ */ jsxs19(Text19, { color: colors.secondaryDim, dimColor: !isSelected, children: [
3547
+ showSource && /* @__PURE__ */ jsxs21(Text21, { color: colors.secondaryDim, dimColor: !isSelected, children: [
3088
3548
  " ",
3089
3549
  sourceName
3090
3550
  ] }),
3091
- showInstalls && skill.installs !== void 0 && /* @__PURE__ */ jsx19(Text19, { color: colors.secondaryDim, children: formatInstalls(skill.installs).padStart(8) })
3551
+ showInstalls && skill.installs !== void 0 && /* @__PURE__ */ jsx21(Text21, { color: colors.secondaryDim, children: formatInstalls(skill.installs).padStart(8) })
3092
3552
  ] }, `${skill.source}-${skill.name}`);
3093
3553
  }),
3094
- skills.length > maxVisible && /* @__PURE__ */ jsx19(Box19, { marginTop: 1, children: /* @__PURE__ */ jsxs19(Text19, { color: colors.secondaryDim, dimColor: true, children: [
3554
+ skills.length > maxVisible && /* @__PURE__ */ jsx21(Box21, { marginTop: 1, children: /* @__PURE__ */ jsxs21(Text21, { color: colors.secondaryDim, dimColor: true, children: [
3095
3555
  "Showing ",
3096
3556
  startIndex + 1,
3097
3557
  "-",
@@ -3103,11 +3563,11 @@ function SkillList({
3103
3563
  }
3104
3564
 
3105
3565
  // src/components/StatusBar.tsx
3106
- import { Box as Box20, Text as Text20 } from "ink";
3107
- import { jsx as jsx20, jsxs as jsxs20 } from "react/jsx-runtime";
3566
+ import { Box as Box22, Text as Text22 } from "ink";
3567
+ import { jsx as jsx22, jsxs as jsxs22 } from "react/jsx-runtime";
3108
3568
  function StatusBar({ shortcuts, message }) {
3109
- return /* @__PURE__ */ jsxs20(
3110
- Box20,
3569
+ return /* @__PURE__ */ jsxs22(
3570
+ Box22,
3111
3571
  {
3112
3572
  borderStyle: "single",
3113
3573
  borderColor: colors.borderDim,
@@ -3118,11 +3578,11 @@ function StatusBar({ shortcuts, message }) {
3118
3578
  paddingX: 1,
3119
3579
  justifyContent: "space-between",
3120
3580
  children: [
3121
- /* @__PURE__ */ jsx20(Box20, { gap: 2, children: shortcuts.map((shortcut, idx) => /* @__PURE__ */ jsxs20(Box20, { gap: 1, children: [
3122
- /* @__PURE__ */ jsx20(Text20, { color: colors.primary, bold: true, children: shortcut.key }),
3123
- /* @__PURE__ */ jsx20(Text20, { color: colors.secondaryDim, children: shortcut.label })
3581
+ /* @__PURE__ */ jsx22(Box22, { gap: 2, children: shortcuts.map((shortcut, idx) => /* @__PURE__ */ jsxs22(Box22, { gap: 1, children: [
3582
+ /* @__PURE__ */ jsx22(Text22, { color: colors.primary, bold: true, children: shortcut.key }),
3583
+ /* @__PURE__ */ jsx22(Text22, { color: colors.secondaryDim, children: shortcut.label })
3124
3584
  ] }, idx)) }),
3125
- message && /* @__PURE__ */ jsxs20(Text20, { color: colors.success, children: [
3585
+ message && /* @__PURE__ */ jsxs22(Text22, { color: colors.success, children: [
3126
3586
  symbols.check,
3127
3587
  " ",
3128
3588
  message
@@ -3133,44 +3593,44 @@ function StatusBar({ shortcuts, message }) {
3133
3593
  }
3134
3594
 
3135
3595
  // src/components/SearchInput.tsx
3136
- import { Box as Box21, Text as Text21 } from "ink";
3596
+ import { Box as Box23, Text as Text23 } from "ink";
3137
3597
  import TextInput2 from "ink-text-input";
3138
- import { jsx as jsx21, jsxs as jsxs21 } from "react/jsx-runtime";
3598
+ import { jsx as jsx23, jsxs as jsxs23 } from "react/jsx-runtime";
3139
3599
  function SearchInput({
3140
3600
  value,
3141
3601
  onChange,
3142
3602
  placeholder = "Search skills...",
3143
3603
  isFocused = false
3144
3604
  }) {
3145
- return /* @__PURE__ */ jsxs21(
3146
- Box21,
3605
+ return /* @__PURE__ */ jsxs23(
3606
+ Box23,
3147
3607
  {
3148
3608
  borderStyle: "single",
3149
3609
  borderColor: isFocused ? colors.primary : colors.borderDim,
3150
3610
  paddingX: 1,
3151
3611
  children: [
3152
- /* @__PURE__ */ jsx21(Text21, { color: colors.secondaryDim, children: "/ " }),
3153
- isFocused ? /* @__PURE__ */ jsx21(
3612
+ /* @__PURE__ */ jsx23(Text23, { color: colors.secondaryDim, children: "/ " }),
3613
+ isFocused ? /* @__PURE__ */ jsx23(
3154
3614
  TextInput2,
3155
3615
  {
3156
3616
  value,
3157
3617
  onChange,
3158
3618
  placeholder
3159
3619
  }
3160
- ) : /* @__PURE__ */ jsx21(Text21, { color: value ? colors.secondary : colors.secondaryDim, children: value || placeholder }),
3161
- /* @__PURE__ */ jsx21(Box21, { flexGrow: 1 }),
3162
- /* @__PURE__ */ jsx21(Text21, { color: colors.secondaryDim, children: "/" })
3620
+ ) : /* @__PURE__ */ jsx23(Text23, { color: value ? colors.secondary : colors.secondaryDim, children: value || placeholder }),
3621
+ /* @__PURE__ */ jsx23(Box23, { flexGrow: 1 }),
3622
+ /* @__PURE__ */ jsx23(Text23, { color: colors.secondaryDim, children: "/" })
3163
3623
  ]
3164
3624
  }
3165
3625
  );
3166
3626
  }
3167
3627
 
3168
3628
  // src/hooks/useKeyboard.ts
3169
- import { useState as useState20, useCallback as useCallback3, useEffect as useEffect16 } from "react";
3170
- import { useInput as useInput16, useApp as useApp2 } from "ink";
3629
+ import { useState as useState22, useCallback as useCallback3, useEffect as useEffect18 } from "react";
3630
+ import { useInput as useInput18, useApp as useApp2 } from "ink";
3171
3631
  function useKeyboard(options = {}) {
3172
3632
  const { exit } = useApp2();
3173
- useInput16((input, key) => {
3633
+ useInput18((input, key) => {
3174
3634
  if (options.disabled) return;
3175
3635
  if (input === "q" || key.ctrl && input === "c") {
3176
3636
  exit();
@@ -3214,8 +3674,8 @@ function useKeyboard(options = {}) {
3214
3674
  });
3215
3675
  }
3216
3676
  function useListNavigation(listLength, initialIndex = 0) {
3217
- const [selectedIndex, setSelectedIndex] = useState20(initialIndex);
3218
- useEffect16(() => {
3677
+ const [selectedIndex, setSelectedIndex] = useState22(initialIndex);
3678
+ useEffect18(() => {
3219
3679
  if (selectedIndex >= listLength && listLength > 0) {
3220
3680
  setSelectedIndex(listLength - 1);
3221
3681
  }
@@ -3233,7 +3693,7 @@ function useListNavigation(listLength, initialIndex = 0) {
3233
3693
  }
3234
3694
 
3235
3695
  // src/hooks/useMemory.ts
3236
- import { useState as useState21, useEffect as useEffect17, useCallback as useCallback4 } from "react";
3696
+ import { useState as useState23, useEffect as useEffect19, useCallback as useCallback4 } from "react";
3237
3697
  import {
3238
3698
  LearningStore as LearningStore2,
3239
3699
  ObservationStore as ObservationStore2,
@@ -3241,12 +3701,12 @@ import {
3241
3701
  createMemoryInjector as createMemoryInjector2
3242
3702
  } from "@skillkit/core";
3243
3703
  function useMemory() {
3244
- const [learnings, setLearnings] = useState21([]);
3245
- const [observations, setObservations] = useState21([]);
3246
- const [status, setStatus] = useState21(null);
3247
- const [loading, setLoading] = useState21(true);
3248
- const [error, setError] = useState21(null);
3249
- const [isGlobal, setIsGlobal] = useState21(false);
3704
+ const [learnings, setLearnings] = useState23([]);
3705
+ const [observations, setObservations] = useState23([]);
3706
+ const [status, setStatus] = useState23(null);
3707
+ const [loading, setLoading] = useState23(true);
3708
+ const [error, setError] = useState23(null);
3709
+ const [isGlobal, setIsGlobal] = useState23(false);
3250
3710
  const projectPath = process.cwd();
3251
3711
  const refresh = useCallback4(() => {
3252
3712
  setLoading(true);
@@ -3325,7 +3785,7 @@ function useMemory() {
3325
3785
  },
3326
3786
  [projectPath, refresh]
3327
3787
  );
3328
- useEffect17(() => {
3788
+ useEffect19(() => {
3329
3789
  refresh();
3330
3790
  }, [refresh]);
3331
3791
  return {
@@ -3344,10 +3804,10 @@ function useMemory() {
3344
3804
  }
3345
3805
 
3346
3806
  // src/index.tsx
3347
- import { jsx as jsx22 } from "react/jsx-runtime";
3807
+ import { jsx as jsx24 } from "react/jsx-runtime";
3348
3808
  function startTUI() {
3349
3809
  process.stdout.write("\x1B[2J\x1B[0f");
3350
- const { waitUntilExit, clear } = render(/* @__PURE__ */ jsx22(App, {}), {
3810
+ const { waitUntilExit, clear } = render(/* @__PURE__ */ jsx24(App, {}), {
3351
3811
  exitOnCtrlC: true
3352
3812
  });
3353
3813
  return waitUntilExit().then(() => {
@@ -3365,6 +3825,8 @@ export {
3365
3825
  Installed,
3366
3826
  Marketplace,
3367
3827
  Memory,
3828
+ Methodology,
3829
+ Plan,
3368
3830
  Plugins,
3369
3831
  Recommend,
3370
3832
  SearchInput,