@knowledgine/cli 0.1.0 → 0.2.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.
Files changed (87) hide show
  1. package/dist/commands/capture.d.ts +10 -0
  2. package/dist/commands/capture.d.ts.map +1 -0
  3. package/dist/commands/capture.js +132 -0
  4. package/dist/commands/capture.js.map +1 -0
  5. package/dist/commands/demo.d.ts +6 -0
  6. package/dist/commands/demo.d.ts.map +1 -0
  7. package/dist/commands/demo.js +44 -0
  8. package/dist/commands/demo.js.map +1 -0
  9. package/dist/commands/feedback.d.ts +18 -0
  10. package/dist/commands/feedback.d.ts.map +1 -0
  11. package/dist/commands/feedback.js +79 -0
  12. package/dist/commands/feedback.js.map +1 -0
  13. package/dist/commands/ingest.d.ts +8 -0
  14. package/dist/commands/ingest.d.ts.map +1 -0
  15. package/dist/commands/ingest.js +98 -0
  16. package/dist/commands/ingest.js.map +1 -0
  17. package/dist/commands/init.d.ts +2 -0
  18. package/dist/commands/init.d.ts.map +1 -1
  19. package/dist/commands/init.js +294 -37
  20. package/dist/commands/init.js.map +1 -1
  21. package/dist/commands/plugins.d.ts +6 -0
  22. package/dist/commands/plugins.d.ts.map +1 -0
  23. package/dist/commands/plugins.js +40 -0
  24. package/dist/commands/plugins.js.map +1 -0
  25. package/dist/commands/search.d.ts +16 -0
  26. package/dist/commands/search.d.ts.map +1 -0
  27. package/dist/commands/search.js +117 -0
  28. package/dist/commands/search.js.map +1 -0
  29. package/dist/commands/setup.d.ts +14 -0
  30. package/dist/commands/setup.d.ts.map +1 -0
  31. package/dist/commands/setup.js +167 -0
  32. package/dist/commands/setup.js.map +1 -0
  33. package/dist/commands/start.d.ts +1 -0
  34. package/dist/commands/start.d.ts.map +1 -1
  35. package/dist/commands/start.js +82 -15
  36. package/dist/commands/start.js.map +1 -1
  37. package/dist/commands/status.d.ts +5 -0
  38. package/dist/commands/status.d.ts.map +1 -0
  39. package/dist/commands/status.js +121 -0
  40. package/dist/commands/status.js.map +1 -0
  41. package/dist/commands/tool.d.ts +29 -0
  42. package/dist/commands/tool.d.ts.map +1 -0
  43. package/dist/commands/tool.js +247 -0
  44. package/dist/commands/tool.js.map +1 -0
  45. package/dist/commands/upgrade.d.ts +6 -0
  46. package/dist/commands/upgrade.d.ts.map +1 -0
  47. package/dist/commands/upgrade.js +91 -0
  48. package/dist/commands/upgrade.js.map +1 -0
  49. package/dist/index.js +144 -2
  50. package/dist/index.js.map +1 -1
  51. package/dist/lib/demo-manager.d.ts +16 -0
  52. package/dist/lib/demo-manager.d.ts.map +1 -0
  53. package/dist/lib/demo-manager.js +37 -0
  54. package/dist/lib/demo-manager.js.map +1 -0
  55. package/dist/lib/formatter.d.ts +7 -0
  56. package/dist/lib/formatter.d.ts.map +1 -0
  57. package/dist/lib/formatter.js +91 -0
  58. package/dist/lib/formatter.js.map +1 -0
  59. package/dist/lib/indexer.d.ts +4 -1
  60. package/dist/lib/indexer.d.ts.map +1 -1
  61. package/dist/lib/indexer.js +2 -1
  62. package/dist/lib/indexer.js.map +1 -1
  63. package/dist/lib/ingest-watcher.d.ts +20 -0
  64. package/dist/lib/ingest-watcher.d.ts.map +1 -0
  65. package/dist/lib/ingest-watcher.js +44 -0
  66. package/dist/lib/ingest-watcher.js.map +1 -0
  67. package/dist/lib/plugin-loader.d.ts +5 -0
  68. package/dist/lib/plugin-loader.d.ts.map +1 -0
  69. package/dist/lib/plugin-loader.js +27 -0
  70. package/dist/lib/plugin-loader.js.map +1 -0
  71. package/dist/lib/progress.d.ts +57 -0
  72. package/dist/lib/progress.d.ts.map +1 -0
  73. package/dist/lib/progress.js +191 -0
  74. package/dist/lib/progress.js.map +1 -0
  75. package/dist/lib/url-validator.d.ts +2 -0
  76. package/dist/lib/url-validator.d.ts.map +1 -0
  77. package/dist/lib/url-validator.js +17 -0
  78. package/dist/lib/url-validator.js.map +1 -0
  79. package/fixtures/demo/notes/api-design-decisions.md +79 -0
  80. package/fixtures/demo/notes/auth-debugging.md +52 -0
  81. package/fixtures/demo/notes/ci-cd-pipeline.md +90 -0
  82. package/fixtures/demo/notes/code-review-notes.md +71 -0
  83. package/fixtures/demo/notes/database-optimization.md +73 -0
  84. package/fixtures/demo/notes/docker-troubleshooting.md +74 -0
  85. package/fixtures/demo/notes/react-performance.md +66 -0
  86. package/fixtures/demo/notes/typescript-migration.md +80 -0
  87. package/package.json +6 -4
@@ -0,0 +1,79 @@
1
+ ---
2
+ tags:
3
+ - api
4
+ - rest
5
+ - design
6
+ author: demo-user
7
+ project: backend-api
8
+ ---
9
+ # REST API Design Decisions
10
+
11
+ ## Issue: Pagination Strategy
12
+ Needed to decide between offset-based and cursor-based pagination
13
+ for the search results endpoint.
14
+
15
+ ### Decision: Cursor-based pagination
16
+ Offset pagination breaks when items are inserted/deleted during browsing.
17
+
18
+ ```typescript
19
+ // Cursor-based pagination
20
+ interface PaginatedResponse<T> {
21
+ data: T[];
22
+ cursor: string | null; // null means no more pages
23
+ hasMore: boolean;
24
+ }
25
+
26
+ app.get("/api/notes", (req, res) => {
27
+ const { cursor, limit = 20 } = req.query;
28
+ const decoded = cursor ? decodeCursor(cursor) : null;
29
+
30
+ const notes = db.query(
31
+ `SELECT * FROM notes
32
+ WHERE ($1::text IS NULL OR id < $1)
33
+ ORDER BY id DESC LIMIT $2`,
34
+ [decoded?.id, limit + 1]
35
+ );
36
+
37
+ const hasMore = notes.length > limit;
38
+ const data = notes.slice(0, limit);
39
+
40
+ res.json({
41
+ data,
42
+ cursor: hasMore ? encodeCursor(data.at(-1)) : null,
43
+ hasMore,
44
+ });
45
+ });
46
+ ```
47
+
48
+ ## Issue: Error Response Format
49
+ Standardized error responses across all endpoints.
50
+
51
+ ### Solution: RFC 7807 Problem Details
52
+
53
+ ```typescript
54
+ interface ProblemDetail {
55
+ type: string;
56
+ title: string;
57
+ status: number;
58
+ detail: string;
59
+ instance?: string;
60
+ }
61
+
62
+ // Error handler middleware
63
+ app.use((err, req, res, _next) => {
64
+ const problem: ProblemDetail = {
65
+ type: `https://api.example.com/errors/${err.code}`,
66
+ title: err.title || "Internal Server Error",
67
+ status: err.status || 500,
68
+ detail: err.message,
69
+ instance: req.originalUrl,
70
+ };
71
+ res.status(problem.status).json(problem);
72
+ });
73
+ ```
74
+
75
+ ## Learnings
76
+ - Cursor-based pagination is more reliable for real-time data
77
+ - Consistent error formats reduce client-side error handling complexity
78
+ - Always version your API from the start (`/v1/`)
79
+ - Document decisions in ADRs for future team members
@@ -0,0 +1,52 @@
1
+ ---
2
+ tags:
3
+ - authentication
4
+ - jwt
5
+ - debugging
6
+ author: demo-user
7
+ project: backend-api
8
+ ---
9
+ # Authentication Debugging Session
10
+
11
+ ## Problem
12
+ JWT token validation was failing intermittently in production.
13
+ Users reported being logged out randomly after 10-15 minutes,
14
+ even though the token expiry was set to 1 hour.
15
+
16
+ ### Error Log
17
+ ```
18
+ Error: TokenExpiredError: jwt expired
19
+ at /app/middleware/auth.ts:42:11
20
+ at processTicksAndRejections (node:internal/process/task_queues:95:5)
21
+ ```
22
+
23
+ ## Investigation
24
+ - Checked server clock sync — NTP was configured correctly
25
+ - Compared token `iat` (issued at) timestamps with server time
26
+ - Found a 45-minute clock skew between API server and auth service
27
+
28
+ ## Solution
29
+ The auth service was running in a container with a drifted system clock.
30
+
31
+ ```typescript
32
+ // Added clock tolerance to JWT verification
33
+ const decoded = jwt.verify(token, SECRET, {
34
+ clockTolerance: 60, // allow 60 seconds of clock skew
35
+ });
36
+ ```
37
+
38
+ Also fixed the root cause by enabling NTP sync in the Docker container:
39
+ ```dockerfile
40
+ RUN apt-get update && apt-get install -y ntpdate
41
+ CMD ntpdate -s pool.ntp.org && node server.js
42
+ ```
43
+
44
+ ## Learnings
45
+ - Always configure clock tolerance for distributed JWT validation
46
+ - Container clocks can drift if the host NTP is not propagated
47
+ - Add monitoring for clock skew between services
48
+ - The `clockTolerance` option is safer than extending token expiry
49
+
50
+ ## Time Spent
51
+ Investigation: 2 hours
52
+ Fix + deployment: 30 minutes
@@ -0,0 +1,90 @@
1
+ ---
2
+ tags:
3
+ - ci-cd
4
+ - github-actions
5
+ - testing
6
+ author: demo-user
7
+ project: infrastructure
8
+ ---
9
+ # CI/CD Pipeline Setup and Debugging
10
+
11
+ ## Problem
12
+ The CI pipeline was taking 25 minutes per push, blocking the
13
+ development workflow. Flaky tests caused unnecessary re-runs.
14
+
15
+ ## Investigation
16
+ Analyzed GitHub Actions run logs:
17
+ - Dependency install: 4 minutes (no caching)
18
+ - Build: 3 minutes
19
+ - Tests: 15 minutes (sequential, with 3 flaky tests)
20
+ - Deploy: 3 minutes
21
+
22
+ ## Solution: Optimized Pipeline
23
+
24
+ ```yaml
25
+ # .github/workflows/ci.yml
26
+ name: CI
27
+ on: [push, pull_request]
28
+
29
+ jobs:
30
+ build-and-test:
31
+ runs-on: ubuntu-latest
32
+ steps:
33
+ - uses: actions/checkout@v4
34
+
35
+ - uses: pnpm/action-setup@v4
36
+ with:
37
+ version: 9
38
+
39
+ - uses: actions/setup-node@v4
40
+ with:
41
+ node-version: 20
42
+ cache: "pnpm"
43
+
44
+ - run: pnpm install --frozen-lockfile
45
+
46
+ - run: pnpm build
47
+
48
+ - run: pnpm test:run --reporter=verbose
49
+ env:
50
+ CI: true
51
+
52
+ lint:
53
+ runs-on: ubuntu-latest
54
+ steps:
55
+ - uses: actions/checkout@v4
56
+ - uses: pnpm/action-setup@v4
57
+ - run: pnpm install --frozen-lockfile
58
+ - run: pnpm lint
59
+ ```
60
+
61
+ ### Flaky Test Fix
62
+ ```typescript
63
+ // Before: timing-dependent test
64
+ it("should debounce input", async () => {
65
+ fireEvent.change(input, { target: { value: "test" } });
66
+ await new Promise((r) => setTimeout(r, 300));
67
+ expect(onSearch).toHaveBeenCalledTimes(1);
68
+ });
69
+
70
+ // After: deterministic with fake timers
71
+ it("should debounce input", () => {
72
+ vi.useFakeTimers();
73
+ fireEvent.change(input, { target: { value: "test" } });
74
+ vi.advanceTimersByTime(300);
75
+ expect(onSearch).toHaveBeenCalledTimes(1);
76
+ vi.useRealTimers();
77
+ });
78
+ ```
79
+
80
+ ## Results
81
+ - Pipeline time: 25 min → 8 min (68% reduction)
82
+ - Flaky test rate: 15% → 0%
83
+ - Developer satisfaction significantly improved
84
+
85
+ ## Learnings
86
+ - Cache dependencies aggressively in CI
87
+ - Run lint and tests in parallel jobs
88
+ - Flaky tests erode trust — fix them immediately
89
+ - Use `--frozen-lockfile` to catch dependency drift
90
+ - Fake timers eliminate timing-based flakiness
@@ -0,0 +1,71 @@
1
+ ---
2
+ tags:
3
+ - code-review
4
+ - best-practices
5
+ - team
6
+ author: demo-user
7
+ project: team-process
8
+ ---
9
+ # Code Review Guidelines and Common Issues
10
+
11
+ ## Problem
12
+ Code reviews were inconsistent. Some PRs got rubber-stamped while
13
+ others received 50+ nitpick comments. Reviews took 2-3 days on average.
14
+
15
+ ## Solution: Review Checklist
16
+
17
+ ### What to Check
18
+ 1. **Correctness**: Does the code do what the PR description says?
19
+ 2. **Edge cases**: Null handling, empty arrays, boundary conditions
20
+ 3. **Security**: Input validation, SQL injection, XSS
21
+ 4. **Tests**: Are new behaviors covered? Are edge cases tested?
22
+ 5. **Naming**: Do variable/function names convey intent?
23
+
24
+ ### Common Issues Found in Reviews
25
+
26
+ #### Error handling gaps
27
+ ```typescript
28
+ // Bad: swallows errors silently
29
+ try {
30
+ await saveUser(data);
31
+ } catch {
32
+ // ignore
33
+ }
34
+
35
+ // Good: handle or propagate with context
36
+ try {
37
+ await saveUser(data);
38
+ } catch (error) {
39
+ logger.error("Failed to save user", { userId: data.id, error });
40
+ throw new ServiceError("User save failed", { cause: error });
41
+ }
42
+ ```
43
+
44
+ #### Missing input validation
45
+ ```typescript
46
+ // Bad: trusts external input
47
+ app.post("/api/users", (req, res) => {
48
+ db.query("INSERT INTO users (name) VALUES ($1)", [req.body.name]);
49
+ });
50
+
51
+ // Good: validate before processing
52
+ app.post("/api/users", (req, res) => {
53
+ const { name } = req.body;
54
+ if (!name || typeof name !== "string" || name.length > 255) {
55
+ return res.status(400).json({ error: "Invalid name" });
56
+ }
57
+ db.query("INSERT INTO users (name) VALUES ($1)", [name]);
58
+ });
59
+ ```
60
+
61
+ ## Process Improvements
62
+ - Max review turnaround: 4 hours for small PRs, 1 day for large
63
+ - Use "Request changes" only for blocking issues
64
+ - Prefix comments: `nit:`, `question:`, `suggestion:`, `blocking:`
65
+ - Author should self-review before requesting review
66
+
67
+ ## Learnings
68
+ - Checklists reduce review inconsistency
69
+ - Small PRs (< 300 lines) get better reviews and faster merges
70
+ - Automate what you can (linting, formatting, type checking)
71
+ - Focus reviews on logic and design, not style
@@ -0,0 +1,73 @@
1
+ ---
2
+ tags:
3
+ - database
4
+ - sql
5
+ - performance
6
+ author: demo-user
7
+ project: backend-api
8
+ ---
9
+ # SQL Query Optimization and Indexing
10
+
11
+ ## Problem
12
+ The notes search endpoint was timing out with 100k+ rows.
13
+ Average query time was 4.2 seconds, causing user-visible latency.
14
+
15
+ ### Slow Query
16
+ ```sql
17
+ SELECT n.*, COUNT(p.id) as pattern_count
18
+ FROM notes n
19
+ LEFT JOIN patterns p ON p.note_id = n.id
20
+ WHERE n.content LIKE '%typescript%'
21
+ AND n.created_at > '2024-01-01'
22
+ GROUP BY n.id
23
+ ORDER BY n.created_at DESC
24
+ LIMIT 20;
25
+ ```
26
+
27
+ ## Investigation
28
+ Used `EXPLAIN ANALYZE` to identify bottlenecks:
29
+ ```sql
30
+ EXPLAIN ANALYZE SELECT ...;
31
+ -- Seq Scan on notes (cost=0.00..12847.00 rows=100234 width=412)
32
+ -- Filter: (content ~~ '%typescript%')
33
+ -- Rows Removed by Filter: 95102
34
+ ```
35
+
36
+ The sequential scan was reading every row.
37
+
38
+ ## Solution: Indexing Strategy
39
+
40
+ ```sql
41
+ -- 1. B-tree index for date range queries
42
+ CREATE INDEX idx_notes_created_at ON notes (created_at DESC);
43
+
44
+ -- 2. Full-text search index instead of LIKE
45
+ CREATE INDEX idx_notes_content_fts ON notes
46
+ USING GIN (to_tsvector('english', content));
47
+
48
+ -- 3. Covering index for the common query pattern
49
+ CREATE INDEX idx_patterns_note_id ON patterns (note_id);
50
+ ```
51
+
52
+ ### Rewritten Query
53
+ ```sql
54
+ SELECT n.*, COUNT(p.id) as pattern_count
55
+ FROM notes n
56
+ LEFT JOIN patterns p ON p.note_id = n.id
57
+ WHERE to_tsvector('english', n.content) @@ plainto_tsquery('typescript')
58
+ AND n.created_at > '2024-01-01'
59
+ GROUP BY n.id
60
+ ORDER BY n.created_at DESC
61
+ LIMIT 20;
62
+ ```
63
+
64
+ ## Results
65
+ - Query time: 4.2s → 18ms (233x improvement)
66
+ - Index storage overhead: ~45MB (acceptable for 100k rows)
67
+
68
+ ## Learnings
69
+ - `LIKE '%term%'` cannot use indexes — always use full-text search
70
+ - `EXPLAIN ANALYZE` is the first tool to reach for
71
+ - Covering indexes avoid table lookups for frequently joined columns
72
+ - Monitor index bloat in write-heavy tables
73
+ - Partial indexes can save space when queries filter on a condition
@@ -0,0 +1,74 @@
1
+ ---
2
+ tags:
3
+ - docker
4
+ - networking
5
+ - devops
6
+ author: demo-user
7
+ project: microservices
8
+ ---
9
+ # Docker Container Networking Issues
10
+
11
+ ## Problem
12
+ Containers in docker-compose could not communicate with each other.
13
+ The API service failed to connect to the database container.
14
+
15
+ ```
16
+ Error: connect ECONNREFUSED 127.0.0.1:5432
17
+ ```
18
+
19
+ ## Investigation
20
+ - Verified both containers were running: `docker ps` showed healthy status
21
+ - Checked network: `docker network ls` showed custom bridge network
22
+ - The API was using `localhost` instead of the service name
23
+
24
+ ## Solution
25
+ Docker containers have their own network namespace. Use the service
26
+ name as the hostname, not `localhost`.
27
+
28
+ ```yaml
29
+ # docker-compose.yml
30
+ services:
31
+ api:
32
+ build: ./api
33
+ environment:
34
+ # Wrong: DB_HOST=localhost
35
+ DB_HOST: postgres # Use service name
36
+ DB_PORT: 5432
37
+ depends_on:
38
+ postgres:
39
+ condition: service_healthy
40
+
41
+ postgres:
42
+ image: postgres:16
43
+ healthcheck:
44
+ test: ["CMD-SHELL", "pg_isready -U app"]
45
+ interval: 5s
46
+ timeout: 3s
47
+ retries: 5
48
+ ```
49
+
50
+ ## Additional Fix: DNS Resolution Timing
51
+ Even with correct hostnames, the API started before DNS was ready.
52
+
53
+ ```typescript
54
+ // Added retry logic for database connection
55
+ async function connectWithRetry(maxRetries = 5): Promise<Pool> {
56
+ for (let i = 0; i < maxRetries; i++) {
57
+ try {
58
+ const pool = new Pool({ host: process.env.DB_HOST });
59
+ await pool.query("SELECT 1");
60
+ return pool;
61
+ } catch (err) {
62
+ console.log(`DB connection attempt ${i + 1} failed, retrying...`);
63
+ await new Promise((r) => setTimeout(r, 2000));
64
+ }
65
+ }
66
+ throw new Error("Could not connect to database");
67
+ }
68
+ ```
69
+
70
+ ## Learnings
71
+ - Never use `localhost` for inter-container communication
72
+ - Use `depends_on` with health checks, not just service ordering
73
+ - Add connection retry logic for resilience
74
+ - `docker network inspect` is useful for debugging DNS issues
@@ -0,0 +1,66 @@
1
+ ---
2
+ tags:
3
+ - react
4
+ - performance
5
+ - frontend
6
+ author: demo-user
7
+ project: dashboard-app
8
+ ---
9
+ # React Performance Optimization
10
+
11
+ ## Issue
12
+ The dashboard page was taking 3+ seconds to render with 500 items.
13
+ React DevTools Profiler showed excessive re-renders on every state change.
14
+
15
+ ## Root Cause Analysis
16
+ 1. Parent component state changes triggered full list re-render
17
+ 2. Inline arrow functions in JSX created new references each render
18
+ 3. Large bundle size from importing entire icon library
19
+
20
+ ## Fix: Memoization
21
+
22
+ ```tsx
23
+ // Before: re-renders on every parent state change
24
+ const ListItem = ({ item, onClick }) => (
25
+ <div onClick={() => onClick(item.id)}>{item.name}</div>
26
+ );
27
+
28
+ // After: memoized with stable callback
29
+ const ListItem = React.memo(({ item, onClick }) => (
30
+ <div onClick={onClick}>{item.name}</div>
31
+ ));
32
+
33
+ // Parent: stable callback reference
34
+ const handleClick = useCallback((id: string) => {
35
+ setSelectedId(id);
36
+ }, []);
37
+ ```
38
+
39
+ ## Fix: Code Splitting
40
+
41
+ ```tsx
42
+ // Before: eager import
43
+ import { AnalyticsChart } from "./AnalyticsChart";
44
+
45
+ // After: lazy loaded
46
+ const AnalyticsChart = React.lazy(() => import("./AnalyticsChart"));
47
+
48
+ function Dashboard() {
49
+ return (
50
+ <Suspense fallback={<Skeleton />}>
51
+ <AnalyticsChart data={data} />
52
+ </Suspense>
53
+ );
54
+ }
55
+ ```
56
+
57
+ ## Results
58
+ - Initial render: 3.2s → 0.8s (75% improvement)
59
+ - Re-render on selection: 450ms → 12ms
60
+ - Bundle size: 1.2MB → 680KB
61
+
62
+ ## Learnings
63
+ - Profile before optimizing — measure actual bottlenecks
64
+ - React.memo only helps when props are actually stable
65
+ - Lazy loading is most effective for below-the-fold content
66
+ - Tree-shaking icon libraries saves significant bundle size
@@ -0,0 +1,80 @@
1
+ ---
2
+ tags:
3
+ - typescript
4
+ - migration
5
+ - refactoring
6
+ author: demo-user
7
+ project: legacy-app
8
+ ---
9
+ # JavaScript to TypeScript Migration
10
+
11
+ ## Problem
12
+ The legacy Express app (50+ files) had no type safety. Runtime errors
13
+ were discovered only in production, and onboarding new developers
14
+ took weeks due to lack of type documentation.
15
+
16
+ ## Migration Strategy
17
+ Adopted an incremental approach instead of a big-bang rewrite.
18
+
19
+ ### Phase 1: Setup (Day 1)
20
+ ```jsonc
21
+ // tsconfig.json - permissive start
22
+ {
23
+ "compilerOptions": {
24
+ "allowJs": true,
25
+ "checkJs": false,
26
+ "strict": false,
27
+ "outDir": "dist",
28
+ "rootDir": "src"
29
+ },
30
+ "include": ["src/**/*"]
31
+ }
32
+ ```
33
+
34
+ ### Phase 2: Rename files (Week 1)
35
+ ```bash
36
+ # Renamed .js → .ts one directory at a time
37
+ # Started with utility files that had no dependencies
38
+ find src/utils -name "*.js" -exec bash -c 'mv "$0" "${0%.js}.ts"' {} \;
39
+ ```
40
+
41
+ ### Phase 3: Add types gradually (Week 2-4)
42
+ ```typescript
43
+ // Before: implicit any everywhere
44
+ function processUser(user) {
45
+ return { name: user.name, role: user.role || "viewer" };
46
+ }
47
+
48
+ // After: explicit types
49
+ interface User {
50
+ id: string;
51
+ name: string;
52
+ role?: "admin" | "editor" | "viewer";
53
+ }
54
+
55
+ function processUser(user: User): { name: string; role: string } {
56
+ return { name: user.name, role: user.role ?? "viewer" };
57
+ }
58
+ ```
59
+
60
+ ### Phase 4: Enable strict mode (Week 5)
61
+ ```jsonc
62
+ {
63
+ "compilerOptions": {
64
+ "strict": true,
65
+ "noUncheckedIndexedAccess": true
66
+ }
67
+ }
68
+ ```
69
+
70
+ ## Results
71
+ - Runtime type errors: 12/month → 0/month
72
+ - Onboarding time: 3 weeks → 1 week
73
+ - Refactoring confidence: significantly improved with IDE support
74
+
75
+ ## Learnings
76
+ - Incremental migration is key — never stop shipping features
77
+ - Start with leaf files (utilities), move inward to core logic
78
+ - `@ts-expect-error` is better than `any` for tracking tech debt
79
+ - Enable `strict` as soon as possible to avoid accumulating debt
80
+ - The build time increase was negligible (< 2 seconds)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knowledgine/cli",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -16,11 +16,13 @@
16
16
  "dependencies": {
17
17
  "chokidar": "^5.0.0",
18
18
  "commander": "^14.0.3",
19
- "@knowledgine/core": "0.1.0",
20
- "@knowledgine/mcp-server": "0.1.0"
19
+ "@knowledgine/core": "0.2.0",
20
+ "@knowledgine/mcp-server": "0.2.0",
21
+ "@knowledgine/ingest": "0.2.0"
21
22
  },
22
23
  "files": [
23
- "dist"
24
+ "dist",
25
+ "fixtures"
24
26
  ],
25
27
  "description": "CLI for indexing markdown files and serving MCP knowledge tools",
26
28
  "mcpName": "io.github.3062-in-zamud/knowledgine",