@sushanglewis/lincoln 1.5.0 → 1.5.2

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 (305) hide show
  1. package/dist/main.d.ts +3 -0
  2. package/dist/main.js +1286 -916
  3. package/dist/main.js.map +1 -1
  4. package/dist/postinstall.d.ts +3 -0
  5. package/dist/postinstall.js +18 -0
  6. package/dist/postinstall.js.map +1 -0
  7. package/framework/.claude/agents/_contract.md +79 -0
  8. package/framework/.claude/agents/architect.md +31 -0
  9. package/framework/.claude/agents/default.md +151 -0
  10. package/framework/.claude/agents/designer.md +33 -0
  11. package/framework/.claude/agents/engineer.md +42 -0
  12. package/framework/.claude/agents/external/NOTICES.md +12 -0
  13. package/framework/.claude/agents/external/everything-claude-code.manifest.yaml +23 -0
  14. package/framework/.claude/agents/external/oh-my-claudecode.manifest.yaml +26 -0
  15. package/framework/.claude/agents/external/wshobson-agents.manifest.yaml +23 -0
  16. package/framework/.claude/agents/frontend-engineer.md +32 -0
  17. package/framework/.claude/agents/knowledge-curator.md +28 -0
  18. package/framework/.claude/agents/pm.md +38 -0
  19. package/framework/.claude/agents/qa.md +28 -0
  20. package/framework/.claude/agents/release-coordinator.md +25 -0
  21. package/framework/.claude/agents/researcher.md +41 -0
  22. package/framework/.claude/harnesses/claude-code.yaml +15 -0
  23. package/framework/.claude/harnesses/codex.yaml +40 -0
  24. package/framework/.claude/harnesses/command-map.yaml +255 -0
  25. package/framework/.claude/harnesses/opencode.yaml +32 -0
  26. package/framework/.claude/harnesses/scenarios.yaml +45 -0
  27. package/framework/.claude/hooks/on-pr-event.sh +69 -0
  28. package/framework/.claude/hooks/on-session-start.sh +427 -0
  29. package/framework/.claude/hooks/on-stop.sh +104 -0
  30. package/framework/.claude/hooks/post-tool-use.sh +161 -0
  31. package/framework/.claude/hooks/pre-tool-use.sh +246 -0
  32. package/framework/.claude/schemas/agent-definition.schema.json +35 -0
  33. package/framework/.claude/schemas/benchmark-report.schema.json +148 -0
  34. package/framework/.claude/schemas/pm-to-ux-handoff.schema.yaml +128 -0
  35. package/framework/.claude/schemas/stage-definition.schema.json +233 -0
  36. package/framework/.claude/schemas/workflow-stage.schema.json +86 -0
  37. package/framework/.claude/schemas/workflow-template.schema.json +88 -0
  38. package/framework/.claude/settings.json +14 -0
  39. package/framework/.claude/skills/build-product-prototype/SKILL.md +35 -0
  40. package/framework/.claude/skills/build-product-prototype/prompts/main.md +78 -0
  41. package/framework/.claude/skills/clarify-requirements/SKILL.md +32 -0
  42. package/framework/.claude/skills/clarify-requirements/prompts/main.md +81 -0
  43. package/framework/.claude/skills/dependencies.yaml +139 -0
  44. package/framework/.claude/skills/draft-product-design/SKILL.md +40 -0
  45. package/framework/.claude/skills/draft-product-design/prompts/main.md +47 -0
  46. package/framework/.claude/skills/lc-analyze-frameworks/SKILL.md +43 -0
  47. package/framework/.claude/skills/lc-analyze-frameworks/prompts/main.md +95 -0
  48. package/framework/.claude/skills/lc-benchmark/SKILL.md +61 -0
  49. package/framework/.claude/skills/lc-build-codebase-knowledge/SKILL.md +38 -0
  50. package/framework/.claude/skills/lc-build-codebase-knowledge/prompts/build-codebase-knowledge.md +61 -0
  51. package/framework/.claude/skills/lc-collect-intelligence/SKILL.md +43 -0
  52. package/framework/.claude/skills/lc-collect-intelligence/prompts/main.md +72 -0
  53. package/framework/.claude/skills/lc-competitive-analysis/SKILL.md +43 -0
  54. package/framework/.claude/skills/lc-competitive-analysis/prompts/main.md +70 -0
  55. package/framework/.claude/skills/lc-explore-opensource/SKILL.md +36 -0
  56. package/framework/.claude/skills/lc-explore-opensource/prompts/explore-opensource.md +77 -0
  57. package/framework/.claude/skills/lc-first-principles/SKILL.md +43 -0
  58. package/framework/.claude/skills/lc-first-principles/prompts/main.md +73 -0
  59. package/framework/.claude/skills/lc-handoff/SKILL.md +34 -0
  60. package/framework/.claude/skills/lc-init-branch/SKILL.md +52 -0
  61. package/framework/.claude/skills/lc-market-research/SKILL.md +43 -0
  62. package/framework/.claude/skills/lc-market-research/prompts/main.md +79 -0
  63. package/framework/.claude/skills/lc-product-research/SKILL.md +43 -0
  64. package/framework/.claude/skills/lc-product-research/prompts/main.md +80 -0
  65. package/framework/.claude/skills/lc-research-report/SKILL.md +43 -0
  66. package/framework/.claude/skills/lc-research-report/prompts/main.md +90 -0
  67. package/framework/.claude/skills/lc-research-scope/SKILL.md +43 -0
  68. package/framework/.claude/skills/lc-research-scope/prompts/main.md +82 -0
  69. package/framework/.claude/skills/lc-setup/SKILL.md +68 -0
  70. package/framework/.claude/skills/lc-setup/prompts/main.md +88 -0
  71. package/framework/.claude/skills/lc-stage/SKILL.md +45 -0
  72. package/framework/.claude/skills/lc-stakeholder-research/SKILL.md +43 -0
  73. package/framework/.claude/skills/lc-stakeholder-research/prompts/main.md +65 -0
  74. package/framework/.claude/skills/lc-status/SKILL.md +25 -0
  75. package/framework/.claude/skills/lc-storytelling/SKILL.md +43 -0
  76. package/framework/.claude/skills/lc-storytelling/prompts/main.md +77 -0
  77. package/framework/.claude/skills/lc-wf/SKILL.md +54 -0
  78. package/framework/.claude/skills/lc-workflow/SKILL.md +48 -0
  79. package/framework/.claude/skills/lc-workflow/validators/validate.py +755 -0
  80. package/framework/.claude/skills/lc-workflow-router/SKILL.md +41 -0
  81. package/framework/.claude/skills/lc-workflow-router/prompts/intake-prompt.md +91 -0
  82. package/framework/.claude/skills/lc-workflow-router/prompts/router-prompt.md +44 -0
  83. package/framework/.claude/skills/plan-tdd-development/SKILL.md +31 -0
  84. package/framework/.claude/skills/plan-tdd-development/prompts/main.md +44 -0
  85. package/framework/.claude/skills/process-interview/SKILL.md +32 -0
  86. package/framework/.claude/skills/process-interview/prompts/main.md +47 -0
  87. package/framework/.claude/skills/propose-with-openspec/SKILL.md +37 -0
  88. package/framework/.claude/skills/propose-with-openspec/prompts/main.md +53 -0
  89. package/framework/.claude/skills/split-to-github/SKILL.md +32 -0
  90. package/framework/.claude/skills/split-to-github/prompts/main.md +42 -0
  91. package/framework/.claude/skills/sync-to-knowledge/SKILL.md +35 -0
  92. package/framework/.claude/skills/sync-to-knowledge/prompts/main.md +54 -0
  93. package/framework/.claude/skills/workflow-continue/SKILL.md +24 -0
  94. package/framework/.claude/skills/workflow-continue/prompts/main.md +25 -0
  95. package/framework/.claude/stages/build-codebase-knowledge.yaml +42 -0
  96. package/framework/.claude/stages/clarify.yaml +59 -0
  97. package/framework/.claude/stages/explore-opensource.yaml +40 -0
  98. package/framework/.claude/stages/implement.yaml +60 -0
  99. package/framework/.claude/stages/ingest.yaml +40 -0
  100. package/framework/.claude/stages/lc-analyze-frameworks.yaml +37 -0
  101. package/framework/.claude/stages/lc-collect-intelligence.yaml +37 -0
  102. package/framework/.claude/stages/lc-competitive-analysis.yaml +37 -0
  103. package/framework/.claude/stages/lc-first-principles.yaml +37 -0
  104. package/framework/.claude/stages/lc-market-research.yaml +37 -0
  105. package/framework/.claude/stages/lc-product-research.yaml +37 -0
  106. package/framework/.claude/stages/lc-research-report.yaml +38 -0
  107. package/framework/.claude/stages/lc-research-scope.yaml +38 -0
  108. package/framework/.claude/stages/lc-stakeholder-research.yaml +37 -0
  109. package/framework/.claude/stages/lc-storytelling.yaml +37 -0
  110. package/framework/.claude/stages/product-design-docs.yaml +66 -0
  111. package/framework/.claude/stages/product-prototype.yaml +53 -0
  112. package/framework/.claude/stages/propose.yaml +45 -0
  113. package/framework/.claude/stages/split.yaml +41 -0
  114. package/framework/.claude/stages/sync-knowledge.yaml +49 -0
  115. package/framework/.claude/stages/tdd-development-plan.yaml +43 -0
  116. package/framework/.claude/stages/workflow-router.yaml +45 -0
  117. package/framework/.claude/templates/solo-workflow-context.yaml +23 -0
  118. package/framework/.claude/workflows/README.md +93 -0
  119. package/framework/.claude/workflows/bug-fix.yaml +81 -0
  120. package/framework/.claude/workflows/design-spike.yaml +55 -0
  121. package/framework/.claude/workflows/existing-project-iteration.yaml +106 -0
  122. package/framework/.claude/workflows/interview-to-knowledge.yaml +189 -0
  123. package/framework/.claude/workflows/oss-first-design.yaml +100 -0
  124. package/framework/.claude/workflows/pm-research.yaml +115 -0
  125. package/framework/.claude-plugin/hooks.json +6 -0
  126. package/framework/.claude-plugin/marketplace.json +32 -0
  127. package/framework/.claude-plugin/plugin.json +57 -0
  128. package/framework/.version-bump.json +43 -0
  129. package/framework/CLAUDE.md +140 -0
  130. package/framework/CONTRIBUTING.md +219 -0
  131. package/framework/LICENSE +21 -0
  132. package/framework/README.en.md +139 -0
  133. package/framework/README.md +139 -0
  134. package/framework/RELEASE.md +334 -0
  135. package/framework/SKILL.md +24 -0
  136. package/framework/USAGE.md +356 -0
  137. package/framework/manifest.json +1214 -0
  138. package/framework/requirements.txt +4 -0
  139. package/framework/scripts/__init__.py +0 -0
  140. package/framework/scripts/build_codebase_knowledge.py +76 -0
  141. package/framework/scripts/bump_version.py +181 -0
  142. package/framework/scripts/check-dependency-drift.py +69 -0
  143. package/framework/scripts/check-harness-drift.sh +57 -0
  144. package/framework/scripts/check-main-merge-hygiene.py +128 -0
  145. package/framework/scripts/check-skill-dependencies.sh +124 -0
  146. package/framework/scripts/init-lincoln-branch.sh +300 -0
  147. package/framework/scripts/init-project.sh +184 -0
  148. package/framework/scripts/lc-benchmark-cli.py +66 -0
  149. package/framework/scripts/lincoln-audit.py +288 -0
  150. package/framework/scripts/lincoln-setup.py +651 -0
  151. package/framework/scripts/lincoln-status.py +448 -0
  152. package/framework/scripts/lincoln_benchmark.py +224 -0
  153. package/framework/scripts/lincoln_benchmark_eval.py +104 -0
  154. package/framework/scripts/lincoln_benchmark_metrics.py +818 -0
  155. package/framework/scripts/lincoln_benchmark_report.py +141 -0
  156. package/framework/scripts/lincoln_command_map.py +289 -0
  157. package/framework/scripts/lincoln_dependency_manager.py +335 -0
  158. package/framework/scripts/lincoln_documents.py +175 -0
  159. package/framework/scripts/lincoln_harness_adapter.py +319 -0
  160. package/framework/scripts/lincoln_index.py +255 -0
  161. package/framework/scripts/lincoln_paths.py +198 -0
  162. package/framework/scripts/lincoln_prd.py +227 -0
  163. package/framework/scripts/lincoln_role.py +46 -0
  164. package/framework/scripts/lincoln_scenario.py +59 -0
  165. package/framework/scripts/lincoln_session_start_metrics.py +71 -0
  166. package/framework/scripts/lincoln_skill_prompt.py +48 -0
  167. package/framework/scripts/lincoln_trace.py +335 -0
  168. package/framework/scripts/lincoln_workflow.py +199 -0
  169. package/framework/scripts/list-active-lincoln-branches.sh +87 -0
  170. package/framework/scripts/package-lincoln-plugin.py +340 -0
  171. package/framework/scripts/run-infrastructure-tests.py +84 -0
  172. package/framework/scripts/stage_loader.py +1071 -0
  173. package/framework/scripts/static-check.sh +356 -0
  174. package/framework/scripts/sync-external-agents.sh +210 -0
  175. package/framework/scripts/sync-framework-package.mjs +218 -0
  176. package/framework/scripts/task_tool_guard.py +213 -0
  177. package/framework/scripts/track-artifacts.py +140 -0
  178. package/framework/scripts/validate_stage.py +350 -0
  179. package/{README.md → framework/tools/lincoln/README.md} +4 -4
  180. package/framework/tools/lincoln/package-lock.json +3349 -0
  181. package/framework/tools/lincoln/package.json +48 -0
  182. package/framework/tools/lincoln/src/cli.tsx +60 -0
  183. package/framework/tools/lincoln/src/components/AudioMeter.tsx +34 -0
  184. package/framework/tools/lincoln/src/components/CancelledScreen.tsx +11 -0
  185. package/framework/tools/lincoln/src/components/DevicesMenu.tsx +79 -0
  186. package/framework/tools/lincoln/src/components/HintBar.tsx +25 -0
  187. package/framework/tools/lincoln/src/components/LogView.tsx +36 -0
  188. package/framework/tools/lincoln/src/components/ModelMenu.tsx +122 -0
  189. package/framework/tools/lincoln/src/components/ReadyScreen.tsx +54 -0
  190. package/framework/tools/lincoln/src/components/RecordingApp.tsx +211 -0
  191. package/framework/tools/lincoln/src/components/RecordingScreen.tsx +41 -0
  192. package/framework/tools/lincoln/src/components/SelectMenu.tsx +53 -0
  193. package/framework/tools/lincoln/src/components/StatusPanel.tsx +52 -0
  194. package/framework/tools/lincoln/src/components/StopConfirmation.tsx +32 -0
  195. package/framework/tools/lincoln/src/config/args.ts +35 -0
  196. package/framework/tools/lincoln/src/config/loadConfig.ts +81 -0
  197. package/framework/tools/lincoln/src/config/resolveConfig.ts +85 -0
  198. package/framework/tools/lincoln/src/devices/listDevices.ts +11 -0
  199. package/framework/tools/lincoln/src/devices/parseDevices.ts +25 -0
  200. package/framework/tools/lincoln/src/hooks/useKeyHandler.ts +63 -0
  201. package/framework/tools/lincoln/src/main.tsx +4 -0
  202. package/framework/tools/lincoln/src/models/models.ts +34 -0
  203. package/framework/tools/lincoln/src/models/runWarmup.ts +46 -0
  204. package/framework/tools/lincoln/src/models/warmupProgress.ts +30 -0
  205. package/framework/tools/lincoln/src/recording/spawnRecorder.ts +127 -0
  206. package/framework/tools/lincoln/src/recording/useRecorder.ts +146 -0
  207. package/framework/tools/lincoln/src/utils/amplitudeToMeter.ts +4 -0
  208. package/framework/tools/lincoln/src/utils/formatDuration.ts +6 -0
  209. package/framework/tools/lincoln/src/utils/sessionId.ts +25 -0
  210. package/framework/tools/lincoln/tests/cli.test.tsx +52 -0
  211. package/framework/tools/lincoln/tests/components/AudioMeter.test.tsx +31 -0
  212. package/framework/tools/lincoln/tests/components/CancelledScreen.test.tsx +12 -0
  213. package/framework/tools/lincoln/tests/components/ReadyScreen.test.tsx +68 -0
  214. package/framework/tools/lincoln/tests/components/RecordingApp.menus.test.tsx +158 -0
  215. package/framework/tools/lincoln/tests/components/RecordingApp.test.tsx +248 -0
  216. package/framework/tools/lincoln/tests/components/RecordingScreen.test.tsx +37 -0
  217. package/framework/tools/lincoln/tests/components/SelectMenu.test.tsx +59 -0
  218. package/framework/tools/lincoln/tests/components/StopConfirmation.test.tsx +38 -0
  219. package/framework/tools/lincoln/tests/config/args.test.ts +49 -0
  220. package/framework/tools/lincoln/tests/config/loadConfig.test.ts +59 -0
  221. package/framework/tools/lincoln/tests/config/resolveConfig.test.ts +72 -0
  222. package/framework/tools/lincoln/tests/devices/parseDevices.test.ts +21 -0
  223. package/framework/tools/lincoln/tests/hooks/useKeyHandler.enabled.test.tsx +44 -0
  224. package/framework/tools/lincoln/tests/hooks/useKeyHandler.test.tsx +130 -0
  225. package/framework/tools/lincoln/tests/models/models.test.ts +27 -0
  226. package/framework/tools/lincoln/tests/models/warmupProgress.test.ts +25 -0
  227. package/framework/tools/lincoln/tests/recording/spawnRecorder.test.ts +85 -0
  228. package/framework/tools/lincoln/tests/recording/useRecorder.test.tsx +172 -0
  229. package/framework/tools/lincoln/tests/utils/amplitudeToMeter.test.ts +22 -0
  230. package/framework/tools/lincoln/tests/utils/formatDuration.test.ts +11 -0
  231. package/framework/tools/lincoln/tests/utils/sessionId.test.ts +30 -0
  232. package/framework/tools/lincoln/tsconfig.json +22 -0
  233. package/framework/tools/lincoln/tsconfig.tests.json +10 -0
  234. package/framework/tools/lincoln/tsup.config.ts +17 -0
  235. package/framework/tools/lincoln/vitest.config.ts +20 -0
  236. package/framework/tools/lincoln-installer/package-lock.json +3611 -0
  237. package/framework/tools/lincoln-installer/package.json +53 -0
  238. package/framework/tools/lincoln-installer/src/cli.tsx +63 -0
  239. package/framework/tools/lincoln-installer/src/components/HarnessSelectScreen.tsx +43 -0
  240. package/framework/tools/lincoln-installer/src/components/InstallerApp.tsx +98 -0
  241. package/framework/tools/lincoln-installer/src/components/OptionsScreen.tsx +56 -0
  242. package/framework/tools/lincoln-installer/src/components/ProgressScreen.tsx +25 -0
  243. package/framework/tools/lincoln-installer/src/components/ResultScreen.tsx +40 -0
  244. package/framework/tools/lincoln-installer/src/components/SelectMenu.tsx +73 -0
  245. package/framework/tools/lincoln-installer/src/components/SummaryScreen.tsx +49 -0
  246. package/framework/tools/lincoln-installer/src/components/UpdateApp.tsx +135 -0
  247. package/framework/tools/lincoln-installer/src/components/WelcomeScreen.tsx +22 -0
  248. package/framework/tools/lincoln-installer/src/config/args.ts +76 -0
  249. package/framework/tools/lincoln-installer/src/config/resolveConfig.ts +33 -0
  250. package/framework/tools/lincoln-installer/src/config/updateArgs.ts +67 -0
  251. package/framework/tools/lincoln-installer/src/hooks/useSetup.ts +149 -0
  252. package/framework/tools/lincoln-installer/src/main.tsx +11 -0
  253. package/framework/tools/lincoln-installer/src/types.ts +19 -0
  254. package/framework/tools/lincoln-installer/src/update-main.tsx +11 -0
  255. package/framework/tools/lincoln-installer/src/update.tsx +90 -0
  256. package/framework/tools/lincoln-installer/src/utils/detectHarness.ts +51 -0
  257. package/framework/tools/lincoln-installer/src/utils/runSetup.ts +62 -0
  258. package/framework/tools/lincoln-installer/src/utils/updateRelease.ts +454 -0
  259. package/framework/tools/lincoln-installer/tests/components/InstallerApp.test.tsx +88 -0
  260. package/framework/tools/lincoln-installer/tests/components/SelectMenu.test.tsx +26 -0
  261. package/framework/tools/lincoln-installer/tests/components/UpdateApp.test.tsx +170 -0
  262. package/framework/tools/lincoln-installer/tests/components/screens.test.tsx +310 -0
  263. package/framework/tools/lincoln-installer/tests/config/args.test.ts +66 -0
  264. package/framework/tools/lincoln-installer/tests/config/resolveConfig.test.ts +75 -0
  265. package/framework/tools/lincoln-installer/tests/config/updateArgs.test.ts +52 -0
  266. package/framework/tools/lincoln-installer/tests/hooks/useSetup.test.tsx +213 -0
  267. package/framework/tools/lincoln-installer/tests/update.test.tsx +108 -0
  268. package/framework/tools/lincoln-installer/tests/utils/detectHarness.test.ts +40 -0
  269. package/framework/tools/lincoln-installer/tests/utils/runSetup.test.ts +45 -0
  270. package/framework/tools/lincoln-installer/tests/utils/updateRelease.test.ts +559 -0
  271. package/framework/tools/lincoln-installer/tsconfig.json +22 -0
  272. package/framework/tools/lincoln-installer/tsconfig.tests.json +8 -0
  273. package/framework/tools/lincoln-installer/tsup.config.ts +17 -0
  274. package/framework/tools/lincoln-installer/vitest.config.ts +20 -0
  275. package/framework/tools/lincoln-record/Cargo.lock +1896 -0
  276. package/framework/tools/lincoln-record/Cargo.toml +24 -0
  277. package/framework/tools/lincoln-record/diarize/diarize.py +117 -0
  278. package/framework/tools/lincoln-record/diarize/merge.py +55 -0
  279. package/framework/tools/lincoln-record/src/audio/capture/microphone.rs +194 -0
  280. package/framework/tools/lincoln-record/src/audio/capture/mod.rs +1 -0
  281. package/framework/tools/lincoln-record/src/audio/devices.rs +20 -0
  282. package/framework/tools/lincoln-record/src/audio/mod.rs +5 -0
  283. package/framework/tools/lincoln-record/src/audio/resampler.rs +44 -0
  284. package/framework/tools/lincoln-record/src/audio/saver.rs +87 -0
  285. package/framework/tools/lincoln-record/src/audio/source.rs +104 -0
  286. package/framework/tools/lincoln-record/src/cli.rs +96 -0
  287. package/framework/tools/lincoln-record/src/config.rs +135 -0
  288. package/framework/tools/lincoln-record/src/lib.rs +6 -0
  289. package/framework/tools/lincoln-record/src/main.rs +242 -0
  290. package/framework/tools/lincoln-record/src/model/mod.rs +248 -0
  291. package/framework/tools/lincoln-record/src/output/metadata.rs +30 -0
  292. package/framework/tools/lincoln-record/src/output/mod.rs +2 -0
  293. package/framework/tools/lincoln-record/src/output/transcript.rs +42 -0
  294. package/framework/tools/lincoln-record/src/transcription/diarization.rs +64 -0
  295. package/framework/tools/lincoln-record/src/transcription/mod.rs +3 -0
  296. package/framework/tools/lincoln-record/src/transcription/provider.rs +43 -0
  297. package/framework/tools/lincoln-record/src/transcription/whisper.rs +176 -0
  298. package/framework/tools/lincoln-record/tests/cli_args.rs +103 -0
  299. package/framework/tools/lincoln-record/tests/config_test.rs +70 -0
  300. package/framework/tools/lincoln-record/tests/devices_test.rs +23 -0
  301. package/framework/tools/lincoln-record/tests/diarization_tests.rs +101 -0
  302. package/framework/tools/lincoln-record/tests/integration_tests.rs +44 -0
  303. package/framework/tools/lincoln-record/tests/model_test.rs +68 -0
  304. package/framework/tools/lincoln-record/tests/transcription_tests.rs +73 -0
  305. package/package.json +19 -13
@@ -0,0 +1,41 @@
1
+ import { Box, Text } from 'ink'
2
+ import React from 'react'
3
+
4
+ import { AudioMeter } from './AudioMeter'
5
+ import { formatDuration } from '../utils/formatDuration'
6
+
7
+ export interface RecordingScreenProps {
8
+ sessionId: string
9
+ topic: string
10
+ designId: string
11
+ duration: number
12
+ amplitude: number
13
+ audioMeterStyle?: 'bar' | 'dot' | 'wave'
14
+ }
15
+
16
+ export function RecordingScreen({
17
+ sessionId,
18
+ topic,
19
+ designId,
20
+ duration,
21
+ amplitude,
22
+ audioMeterStyle = 'bar',
23
+ }: RecordingScreenProps) {
24
+ return (
25
+ <Box flexDirection="column" padding={1}>
26
+ <Text bold>Lincoln Recorder</Text>
27
+ <Text dimColor>Session: {sessionId}</Text>
28
+ {topic ? <Text>Topic: {topic}</Text> : null}
29
+ {designId ? <Text>Design: {designId}</Text> : null}
30
+ <Text />
31
+ <Box>
32
+ <Text color="red">●</Text>
33
+ <Text> Recording {formatDuration(duration)}</Text>
34
+ </Box>
35
+ <Text />
36
+ <AudioMeter amplitude={amplitude} style={audioMeterStyle} />
37
+ <Text />
38
+ <Text dimColor>Press Enter to stop · Press q to cancel</Text>
39
+ </Box>
40
+ )
41
+ }
@@ -0,0 +1,53 @@
1
+ import { Box, Text, useInput } from 'ink'
2
+ import React, { useState } from 'react'
3
+
4
+ export interface SelectMenuItem {
5
+ key: string
6
+ label: string
7
+ }
8
+
9
+ export interface SelectMenuProps {
10
+ title: string
11
+ items: SelectMenuItem[]
12
+ onSelect: (key: string) => void
13
+ onClose: () => void
14
+ footer?: string
15
+ }
16
+
17
+ export function SelectMenu({ title, items, onSelect, onClose, footer }: SelectMenuProps) {
18
+ const [index, setIndex] = useState(0)
19
+
20
+ useInput((_input, key) => {
21
+ if (key.escape) {
22
+ onClose()
23
+ return
24
+ }
25
+ if (key.upArrow) {
26
+ setIndex(i => (i > 0 ? i - 1 : items.length - 1))
27
+ return
28
+ }
29
+ if (key.downArrow) {
30
+ setIndex(i => (i < items.length - 1 ? i + 1 : 0))
31
+ return
32
+ }
33
+ if (key.return && items.length > 0) {
34
+ onSelect(items[Math.min(index, items.length - 1)].key)
35
+ }
36
+ })
37
+
38
+ return (
39
+ <Box flexDirection="column" paddingX={1}>
40
+ <Text bold>{title}</Text>
41
+ {items.length === 0 ? (
42
+ <Text dimColor>(none)</Text>
43
+ ) : (
44
+ items.map((item, i) => (
45
+ <Text key={item.key} color={i === index ? 'cyan' : undefined}>
46
+ {i === index ? '›' : ' '} {item.label}
47
+ </Text>
48
+ ))
49
+ )}
50
+ {footer ? <Text dimColor>{footer}</Text> : null}
51
+ </Box>
52
+ )
53
+ }
@@ -0,0 +1,52 @@
1
+ import { Box, Text } from 'ink'
2
+ import React from 'react'
3
+
4
+ import { formatDuration } from '../utils/formatDuration'
5
+
6
+ export interface StatusPanelProps {
7
+ sessionId: string
8
+ topic?: string
9
+ designId?: string
10
+ branch?: string
11
+ status: 'idle' | 'recording' | 'stopped' | 'cancelled' | 'error'
12
+ duration: number
13
+ amplitude?: number
14
+ }
15
+
16
+ export function StatusPanel({
17
+ sessionId,
18
+ topic,
19
+ designId,
20
+ branch,
21
+ status,
22
+ duration,
23
+ }: StatusPanelProps) {
24
+ const statusLabel = {
25
+ idle: 'Ready',
26
+ recording: `Recording ${formatDuration(duration)}`,
27
+ stopped: 'Stopped',
28
+ cancelled: 'Cancelled',
29
+ error: 'Error',
30
+ }[status]
31
+
32
+ const statusColor = status === 'recording' ? 'red' : status === 'error' ? 'red' : status === 'cancelled' ? 'yellow' : 'green'
33
+
34
+ return (
35
+ <Box flexDirection="column" paddingX={1} paddingTop={1}>
36
+ <Box flexDirection="row" justifyContent="space-between" alignItems="center">
37
+ <Text bold color="white">Lincoln Recorder</Text>
38
+ <Box flexDirection="row" gap={1}>
39
+ <Text color={statusColor}>{status === 'recording' ? '●' : '○'}</Text>
40
+ <Text>{statusLabel}</Text>
41
+ </Box>
42
+ </Box>
43
+
44
+ <Box flexDirection="column" paddingY={1}>
45
+ <Text dimColor>Session: {sessionId}</Text>
46
+ {topic ? <Text dimColor>Topic: {topic}</Text> : null}
47
+ {designId ? <Text dimColor>Design: {designId}</Text> : null}
48
+ {branch ? <Text dimColor>Branch: {branch}</Text> : null}
49
+ </Box>
50
+ </Box>
51
+ )
52
+ }
@@ -0,0 +1,32 @@
1
+ import { Box, Text, useInput } from 'ink'
2
+ import React from 'react'
3
+
4
+ export interface StopConfirmationProps {
5
+ sessionId: string
6
+ workspaceRoot?: string
7
+ onConfirm: () => void
8
+ onCancel?: () => void
9
+ }
10
+
11
+ export function StopConfirmation({ sessionId, workspaceRoot, onConfirm, onCancel }: StopConfirmationProps) {
12
+ const command = `claude process-interview ${sessionId}`
13
+
14
+ useInput(() => {
15
+ onConfirm()
16
+ })
17
+
18
+ return (
19
+ <Box flexDirection="column" padding={1}>
20
+ <Text bold>Stopped</Text>
21
+ <Text>Session {sessionId} saved.</Text>
22
+ {workspaceRoot ? <Text color="gray">Workspace: {workspaceRoot}</Text> : null}
23
+ <Box paddingY={1} flexDirection="column">
24
+ <Text>Run this command in your terminal to generate knowledge artifacts:</Text>
25
+ <Text color="cyan">{command}</Text>
26
+ </Box>
27
+ {onCancel
28
+ ? <Text color="gray">[any key] Copy command and exit · [n] Exit without copying</Text>
29
+ : <Text color="gray">[any key] Exit</Text>}
30
+ </Box>
31
+ )
32
+ }
@@ -0,0 +1,35 @@
1
+ import { parseArgs as nodeParseArgs } from 'node:util'
2
+
3
+ export interface ParsedArgs {
4
+ topic?: string
5
+ designId?: string
6
+ branch?: string
7
+ sessionId?: string
8
+ noTui: boolean
9
+ help: boolean
10
+ }
11
+
12
+ export function parseArgs(argv: string[]): ParsedArgs {
13
+ const { values } = nodeParseArgs({
14
+ args: argv,
15
+ options: {
16
+ topic: { type: 'string' },
17
+ 'design-id': { type: 'string' },
18
+ branch: { type: 'string' },
19
+ 'session-id': { type: 'string' },
20
+ 'no-tui': { type: 'boolean', default: false },
21
+ help: { type: 'boolean', short: 'h', default: false },
22
+ },
23
+ strict: false,
24
+ allowPositionals: true,
25
+ })
26
+
27
+ return {
28
+ topic: values.topic as string | undefined,
29
+ designId: values['design-id'] as string | undefined,
30
+ branch: values.branch as string | undefined,
31
+ sessionId: values['session-id'] as string | undefined,
32
+ noTui: values['no-tui'] as boolean,
33
+ help: values.help as boolean,
34
+ }
35
+ }
@@ -0,0 +1,81 @@
1
+ import { readFileSync } from 'node:fs'
2
+ import { PathLike } from 'node:fs'
3
+
4
+ import yaml from 'js-yaml'
5
+
6
+ export interface LincolnConfig {
7
+ defaultTopic?: string
8
+ defaultDesignId?: string
9
+ defaultBranch?: string
10
+ autoProcess?: boolean
11
+ showAudioMeter?: boolean
12
+ audioMeterStyle?: 'bar' | 'dot' | 'wave'
13
+ }
14
+
15
+ function parseConfig(content: string, path: PathLike): LincolnConfig {
16
+ const trimmed = content.trim()
17
+ if (!trimmed) {
18
+ return {}
19
+ }
20
+
21
+ const isJson = trimmed.startsWith('{') || trimmed.startsWith('[')
22
+ const raw = isJson ? JSON.parse(trimmed) : yaml.load(trimmed)
23
+
24
+ if (raw === null || typeof raw !== 'object') {
25
+ return {}
26
+ }
27
+
28
+ const data = raw as Record<string, unknown>
29
+
30
+ return {
31
+ defaultTopic: asString(data.default_topic),
32
+ defaultDesignId: asString(data.default_design_id),
33
+ defaultBranch: asString(data.default_branch),
34
+ autoProcess: asBoolean(data.auto_process),
35
+ showAudioMeter: asBoolean(data.show_audio_meter),
36
+ audioMeterStyle: asMeterStyle(data.audio_meter_style),
37
+ }
38
+ }
39
+
40
+ function asString(value: unknown): string | undefined {
41
+ return typeof value === 'string' ? value : undefined
42
+ }
43
+
44
+ function asBoolean(value: unknown): boolean | undefined {
45
+ return typeof value === 'boolean' ? value : undefined
46
+ }
47
+
48
+ function asMeterStyle(value: unknown): LincolnConfig['audioMeterStyle'] {
49
+ if (value === 'bar' || value === 'dot' || value === 'wave') {
50
+ return value
51
+ }
52
+ return undefined
53
+ }
54
+
55
+ export function loadConfig(path: PathLike): LincolnConfig {
56
+ let content: string
57
+ try {
58
+ content = readFileSync(path, 'utf-8')
59
+ } catch (error) {
60
+ throw new Error(`Config file not found: ${String(path)}`)
61
+ }
62
+
63
+ try {
64
+ return parseConfig(content, path)
65
+ } catch (error) {
66
+ const cause = error instanceof Error ? error.message : String(error)
67
+ throw new Error(`Failed to parse config ${String(path)}: ${cause}`)
68
+ }
69
+ }
70
+
71
+ export function loadConfigOptional(path: PathLike): LincolnConfig {
72
+ try {
73
+ return loadConfig(path)
74
+ } catch (error) {
75
+ const message = error instanceof Error ? error.message : String(error)
76
+ if (message.includes('Config file not found')) {
77
+ return {}
78
+ }
79
+ throw error
80
+ }
81
+ }
@@ -0,0 +1,85 @@
1
+ import { existsSync } from 'node:fs'
2
+ import { homedir } from 'node:os'
3
+ import { join } from 'node:path'
4
+
5
+ import { LincolnConfig, loadConfigOptional } from './loadConfig'
6
+ import { generateSessionId } from '../utils/sessionId'
7
+
8
+ export interface ParsedArgs {
9
+ topic?: string
10
+ designId?: string
11
+ branch?: string
12
+ sessionId?: string
13
+ noTui?: boolean
14
+ help?: boolean
15
+ }
16
+
17
+ export interface ResolvedConfig extends Required<Pick<LincolnConfig, 'autoProcess' | 'showAudioMeter' | 'audioMeterStyle'>> {
18
+ workspaceRoot: string
19
+ sessionId: string
20
+ topic: string
21
+ designId: string
22
+ branch: string
23
+ noTui: boolean
24
+ }
25
+
26
+ interface ResolveOptions {
27
+ cwd?: string
28
+ home?: string
29
+ now?: Date
30
+ }
31
+
32
+ function pickFirst(...values: Array<string | undefined>): string {
33
+ for (const value of values) {
34
+ if (value !== undefined && value !== '') {
35
+ return value
36
+ }
37
+ }
38
+ return ''
39
+ }
40
+
41
+ function uniqueSessionId(workspaceRoot: string, now: Date, descriptor?: string): string {
42
+ const baseSessionId = generateSessionId({ now, descriptor })
43
+ const recordingPath = join(workspaceRoot, 'recordings', `${baseSessionId}.m4a`)
44
+ if (!existsSync(recordingPath)) {
45
+ return baseSessionId
46
+ }
47
+
48
+ for (let counter = 1; counter <= 999; counter += 1) {
49
+ const candidate = `${baseSessionId}-${String(counter).padStart(3, '0')}`
50
+ const candidatePath = join(workspaceRoot, 'recordings', `${candidate}.m4a`)
51
+ if (!existsSync(candidatePath)) {
52
+ return candidate
53
+ }
54
+ }
55
+
56
+ return baseSessionId
57
+ }
58
+
59
+ export function resolveConfig(args: ParsedArgs, options: ResolveOptions = {}): ResolvedConfig {
60
+ const cwd = options.cwd ?? process.cwd()
61
+ const home = options.home ?? homedir()
62
+ const now = options.now ?? new Date()
63
+
64
+ const globalConfig = loadConfigOptional(join(home, '.lincolnrc'))
65
+ const localConfig = loadConfigOptional(join(cwd, '.lincolnrc'))
66
+
67
+ const topic = pickFirst(args.topic, localConfig.defaultTopic, globalConfig.defaultTopic)
68
+ const designId = pickFirst(args.designId, localConfig.defaultDesignId, globalConfig.defaultDesignId)
69
+ const branch = pickFirst(args.branch, localConfig.defaultBranch, globalConfig.defaultBranch)
70
+
71
+ const descriptor = designId || topic || undefined
72
+ const sessionId = args.sessionId || uniqueSessionId(cwd, now, descriptor)
73
+
74
+ return {
75
+ workspaceRoot: cwd,
76
+ sessionId,
77
+ topic,
78
+ designId,
79
+ branch,
80
+ noTui: args.noTui ?? false,
81
+ autoProcess: localConfig.autoProcess ?? globalConfig.autoProcess ?? false,
82
+ showAudioMeter: localConfig.showAudioMeter ?? globalConfig.showAudioMeter ?? true,
83
+ audioMeterStyle: localConfig.audioMeterStyle ?? globalConfig.audioMeterStyle ?? 'bar',
84
+ }
85
+ }
@@ -0,0 +1,11 @@
1
+ import { execFile } from 'node:child_process'
2
+ import { promisify } from 'node:util'
3
+
4
+ import { parseDevicesOutput, type DeviceList } from './parseDevices'
5
+
6
+ const execFileAsync = promisify(execFile)
7
+
8
+ export async function listDevices(lincolnRecordPath = 'lincoln-record'): Promise<DeviceList> {
9
+ const { stdout } = await execFileAsync(lincolnRecordPath, ['devices'])
10
+ return parseDevicesOutput(stdout)
11
+ }
@@ -0,0 +1,25 @@
1
+ export interface DeviceList {
2
+ defaultDevice: string | null
3
+ devices: string[]
4
+ }
5
+
6
+ const DEFAULT_PREFIX = 'Default input: '
7
+
8
+ export function parseDevicesOutput(output: string): DeviceList {
9
+ let defaultDevice: string | null = null
10
+ const devices: string[] = []
11
+
12
+ for (const rawLine of output.split('\n')) {
13
+ const line = rawLine.trim()
14
+ if (!line) continue
15
+
16
+ if (line.startsWith(DEFAULT_PREFIX)) {
17
+ defaultDevice = line.slice(DEFAULT_PREFIX.length).trim() || null
18
+ continue
19
+ }
20
+
21
+ devices.push(line)
22
+ }
23
+
24
+ return { defaultDevice, devices }
25
+ }
@@ -0,0 +1,63 @@
1
+ import { useInput } from 'ink'
2
+
3
+ export interface KeyHandlerOptions {
4
+ enabled?: boolean
5
+ onRecord?: () => void
6
+ onStop?: () => void
7
+ onCancel?: () => void
8
+ onQuit?: () => void
9
+ onDevices?: () => void
10
+ onModel?: () => void
11
+ onAnyKey?: () => void
12
+ }
13
+
14
+ export function useKeyHandler({
15
+ enabled = true,
16
+ onRecord,
17
+ onStop,
18
+ onCancel,
19
+ onQuit,
20
+ onDevices,
21
+ onModel,
22
+ onAnyKey,
23
+ }: KeyHandlerOptions) {
24
+ useInput(
25
+ (input, key) => {
26
+ if (key.escape || input === 'q' || input === 'Q') {
27
+ onQuit?.()
28
+ return
29
+ }
30
+
31
+ if (key.ctrl && input === 'c') {
32
+ onQuit?.()
33
+ return
34
+ }
35
+
36
+ switch (input) {
37
+ case 'r':
38
+ case 'R':
39
+ onRecord?.()
40
+ return
41
+ case 's':
42
+ case 'S':
43
+ onStop?.()
44
+ return
45
+ case 'c':
46
+ case 'C':
47
+ onCancel?.()
48
+ return
49
+ case 'd':
50
+ case 'D':
51
+ onDevices?.()
52
+ return
53
+ case 'm':
54
+ case 'M':
55
+ onModel?.()
56
+ return
57
+ }
58
+
59
+ onAnyKey?.()
60
+ },
61
+ { isActive: enabled },
62
+ )
63
+ }
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { main } from './cli'
3
+
4
+ main()
@@ -0,0 +1,34 @@
1
+ import { existsSync } from 'node:fs'
2
+ import { homedir } from 'node:os'
3
+ import { join } from 'node:path'
4
+
5
+ export const KNOWN_MODELS = [
6
+ 'tiny',
7
+ 'base',
8
+ 'small',
9
+ 'medium',
10
+ 'large-v1',
11
+ 'large-v2',
12
+ 'large-v3',
13
+ 'large-v3-turbo',
14
+ ]
15
+
16
+ export interface ModelStatus {
17
+ name: string
18
+ cached: boolean
19
+ }
20
+
21
+ export function defaultModelCacheDir(): string {
22
+ return join(homedir(), '.cache', 'lincoln', 'models')
23
+ }
24
+
25
+ export function modelCachePath(name: string, cacheDir: string): string {
26
+ return join(cacheDir, 'whisper', `ggml-${name}.bin`)
27
+ }
28
+
29
+ export function listModelStatuses(cacheDir: string): ModelStatus[] {
30
+ return KNOWN_MODELS.map(name => ({
31
+ name,
32
+ cached: existsSync(modelCachePath(name, cacheDir)),
33
+ }))
34
+ }
@@ -0,0 +1,46 @@
1
+ import { spawn } from 'node:child_process'
2
+
3
+ import { parseWarmupProgress, type WarmupProgress } from './warmupProgress'
4
+
5
+ export interface RunWarmupOptions {
6
+ model: string
7
+ lincolnRecordPath?: string
8
+ onProgress?: (progress: WarmupProgress) => void
9
+ }
10
+
11
+ const READY_LINE = /Model ready at (.+)/
12
+
13
+ export function runWarmup(options: RunWarmupOptions): Promise<string> {
14
+ const { model, lincolnRecordPath = 'lincoln-record', onProgress } = options
15
+
16
+ return new Promise((resolve, reject) => {
17
+ const child = spawn(lincolnRecordPath, ['warmup', '--model', model], {
18
+ stdio: ['ignore', 'pipe', 'pipe'],
19
+ })
20
+
21
+ let readyPath: string | null = null
22
+
23
+ child.stdout.on('data', (data: Buffer) => {
24
+ const match = READY_LINE.exec(data.toString())
25
+ if (match) {
26
+ readyPath = match[1].trim()
27
+ }
28
+ })
29
+
30
+ child.stderr.on('data', (data: Buffer) => {
31
+ const progress = parseWarmupProgress(data.toString())
32
+ if (progress) {
33
+ onProgress?.(progress)
34
+ }
35
+ })
36
+
37
+ child.on('error', reject)
38
+ child.on('exit', code => {
39
+ if (code === 0) {
40
+ resolve(readyPath ?? model)
41
+ } else {
42
+ reject(new Error(`lincoln-record warmup exited with code ${code}`))
43
+ }
44
+ })
45
+ })
46
+ }
@@ -0,0 +1,30 @@
1
+ export interface WarmupProgress {
2
+ downloaded: number
3
+ total: number | null
4
+ percent: number | null
5
+ }
6
+
7
+ const PROGRESS_WITH_TOTAL = /downloaded (\d+) \/ (\d+) bytes \(([\d.]+)%\)/
8
+ const PROGRESS_WITHOUT_TOTAL = /downloaded (\d+) bytes/
9
+
10
+ export function parseWarmupProgress(chunk: string): WarmupProgress | null {
11
+ const withTotal = PROGRESS_WITH_TOTAL.exec(chunk)
12
+ if (withTotal) {
13
+ return {
14
+ downloaded: Number(withTotal[1]),
15
+ total: Number(withTotal[2]),
16
+ percent: Number(withTotal[3]),
17
+ }
18
+ }
19
+
20
+ const withoutTotal = PROGRESS_WITHOUT_TOTAL.exec(chunk)
21
+ if (withoutTotal) {
22
+ return {
23
+ downloaded: Number(withoutTotal[1]),
24
+ total: null,
25
+ percent: null,
26
+ }
27
+ }
28
+
29
+ return null
30
+ }