clikit-plugin 0.2.2 → 0.2.4

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/cli.js CHANGED
@@ -47,27 +47,20 @@ function parseConfig(configPath) {
47
47
  return { config: {}, raw: "", parseError: null };
48
48
  }
49
49
  const content = fs.readFileSync(configPath, "utf-8");
50
- const cleaned = content.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
51
- const cleanedTrailing = cleaned.replace(/,\s*([}\]])/g, "$1");
52
- const parsed = JSON.parse(cleanedTrailing);
53
- return { config: parsed, raw: content, parseError: null };
50
+ try {
51
+ const parsed = JSON.parse(content);
52
+ return { config: parsed, raw: content, parseError: null };
53
+ } catch {
54
+ const cleaned = content.replace(/\/\*[\s\S]*?\*\//g, "");
55
+ const cleanedTrailing = cleaned.replace(/,\s*([}\]])/g, "$1");
56
+ const parsed = JSON.parse(cleanedTrailing);
57
+ return { config: parsed, raw: content, parseError: null };
58
+ }
54
59
  } catch (err) {
55
60
  const raw = fs.existsSync(configPath) ? fs.readFileSync(configPath, "utf-8") : "";
56
61
  return { config: {}, raw, parseError: String(err) };
57
62
  }
58
63
  }
59
- function backupConfig(configPath) {
60
- try {
61
- if (!fs.existsSync(configPath)) {
62
- return null;
63
- }
64
- const backupPath = `${configPath}.backup-${Date.now()}`;
65
- fs.copyFileSync(configPath, backupPath);
66
- return backupPath;
67
- } catch {
68
- return null;
69
- }
70
- }
71
64
  function writeConfig(configPath, config) {
72
65
  ensureConfigDir();
73
66
  const tmpPath = `${configPath}.tmp`;
@@ -90,16 +83,11 @@ async function install() {
90
83
  }
91
84
  const configPath = getConfigPath();
92
85
  try {
93
- const backupPath = backupConfig(configPath);
94
- if (backupPath) {
95
- console.log(` Backup created: ${backupPath}`);
96
- }
97
86
  const result = parseConfig(configPath);
98
87
  if (result.parseError && result.raw.trim()) {
99
88
  console.error(`\u2717 Config file has syntax errors and cannot be safely modified.`);
100
89
  console.error(` Error: ${result.parseError}`);
101
- console.error(` Please fix the config file manually or restore from backup.`);
102
- console.error(` Backup: ${backupPath}`);
90
+ console.error(` Please fix the config file manually.`);
103
91
  return 1;
104
92
  }
105
93
  const config = result.config;
@@ -14,6 +14,6 @@ export interface TodoCheckResult {
14
14
  incomplete: TodoItem[];
15
15
  inProgress: TodoItem[];
16
16
  }
17
- export declare function checkTodoCompletion(todos: TodoItem[]): TodoCheckResult;
17
+ export declare function checkTodoCompletion(todos: unknown): TodoCheckResult;
18
18
  export declare function formatIncompleteWarning(result: TodoCheckResult, sessionId?: string): string;
19
19
  //# sourceMappingURL=todo-enforcer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"todo-enforcer.d.ts","sourceRoot":"","sources":["../../src/hooks/todo-enforcer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,WAAW,CAAC;CAC9C;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,QAAQ,EAAE,CAAC;IACvB,UAAU,EAAE,QAAQ,EAAE,CAAC;CACxB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,eAAe,CAStE;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,eAAe,EACvB,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CAuBR"}
1
+ {"version":3,"file":"todo-enforcer.d.ts","sourceRoot":"","sources":["../../src/hooks/todo-enforcer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,WAAW,CAAC;CAC9C;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,QAAQ,EAAE,CAAC;IACvB,UAAU,EAAE,QAAQ,EAAE,CAAC;CACxB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,CAYnE;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,eAAe,EACvB,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CAuBR"}
package/dist/index.js CHANGED
@@ -3761,6 +3761,9 @@ function filterCommands(commands, config) {
3761
3761
 
3762
3762
  // src/hooks/todo-enforcer.ts
3763
3763
  function checkTodoCompletion(todos) {
3764
+ if (!Array.isArray(todos)) {
3765
+ return { complete: true, incomplete: [], inProgress: [] };
3766
+ }
3764
3767
  const incomplete = todos.filter((t) => t.status === "todo");
3765
3768
  const inProgress = todos.filter((t) => t.status === "in-progress");
3766
3769
  return {
@@ -5588,7 +5591,7 @@ var CliKitPlugin = async (ctx) => {
5588
5591
  const todoConfig = pluginConfig.hooks?.todo_enforcer;
5589
5592
  if (todoConfig?.enabled !== false) {
5590
5593
  const todos = props?.todos;
5591
- if (todos && todos.length > 0) {
5594
+ if (Array.isArray(todos) && todos.length > 0) {
5592
5595
  const result = checkTodoCompletion(todos);
5593
5596
  if (!result.complete && todoConfig?.warn_on_incomplete !== false) {
5594
5597
  console.warn(formatIncompleteWarning(result, sessionID));
@@ -0,0 +1,80 @@
1
+ ---
2
+ date: 2026-02-15
3
+ phase: implementing
4
+ branch: main
5
+ ---
6
+
7
+ # Handoff: CliKit Runtime Bug Fixes
8
+
9
+ ---
10
+
11
+ ## Status Summary
12
+
13
+ CliKit plugin v0.2.3 published with installer merge fix and type guards in hooks. **NEW ISSUES IDENTIFIED**:
14
+ 1. Backup creation is now unnecessary since merge works correctly - should be removed
15
+ 2. Runtime error `todos.filter is not a function` when OpenCode starts
16
+
17
+ ---
18
+
19
+ ## Task Status
20
+
21
+ ### ✅ Completed
22
+ - [x] Fix installer to MERGE with existing opencode.json (v0.2.3)
23
+ - [x] Add defensive type checks to hooks (truncator, security-check, compaction)
24
+ - [x] Publish v0.2.1, v0.2.2, v0.2.3 to npm
25
+
26
+ ### 🔄 In Progress
27
+ - [ ] Remove backup creation from cli.ts
28
+ - [ ] Fix `todos.filter is not a function` runtime error
29
+
30
+ ### 📋 Not Started
31
+ - [ ] Publish v0.2.4
32
+
33
+ ---
34
+
35
+ ## Files Modified
36
+
37
+ | File | Status | Notes |
38
+ |------|--------|-------|
39
+ | `.opencode/src/cli.ts` | Needs Fix | Remove backup logic |
40
+ | `.opencode/src/index.ts` | Needs Fix | Add Array.isArray check |
41
+ | `.opencode/src/hooks/todo-enforcer.ts` | Needs Fix | Add array guard |
42
+
43
+ ---
44
+
45
+ ## Git State
46
+
47
+ - **Branch:** `main`
48
+ - **Last commit:** `31b200c` - Update README with simplified installation
49
+ - **Uncommitted changes:** Yes (8 modified files)
50
+
51
+ ---
52
+
53
+ ## Next Steps
54
+
55
+ 1. [ ] Remove backup logic from cli.ts (delete `backupConfig`, `cleanupOldBackups` functions)
56
+ 2. [ ] Fix `todos.filter` error in `index.ts:172` and `todo-enforcer.ts:20`
57
+ 3. [ ] Run typecheck
58
+ 4. [ ] Publish v0.2.4
59
+
60
+ ---
61
+
62
+ ## Root Cause: `todos.filter` Bug
63
+
64
+ ```typescript
65
+ // Current (broken) - index.ts:166-172
66
+ const todos = props?.todos as Array<{...}> | undefined;
67
+ if (todos && todos.length > 0) { // Objects with .length pass this!
68
+ checkTodoCompletion(todos); // But .filter fails
69
+ }
70
+
71
+ // Fix
72
+ if (Array.isArray(todos) && todos.length > 0) {
73
+ checkTodoCompletion(todos);
74
+ }
75
+ ```
76
+
77
+ **Key files:**
78
+ - `.opencode/src/cli.ts:78-107` — Backup functions to delete
79
+ - `.opencode/src/index.ts:165-180` — Todo handling to fix
80
+ - `.opencode/src/hooks/todo-enforcer.ts:20` — Add array guard
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clikit-plugin",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "OpenCode plugin with 10 agents, 19 commands, 48 skills, 14 hooks",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",