@sushanglewis/lincoln 1.5.0 → 1.5.1

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 +1231 -906
  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,141 @@
1
+ #!/usr/bin/env python3
2
+ """Markdown rendering for Lincoln benchmark reports."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import json
7
+ from typing import Any
8
+
9
+
10
+ def _render_summary(evaluation: dict[str, Any]) -> list[str]:
11
+ if not evaluation:
12
+ return ["- No threshold evaluation available for this scenario yet.", ""]
13
+ red = [m for m, v in evaluation.items() if v.get("status") == "red"]
14
+ yellow = [m for m, v in evaluation.items() if v.get("status") == "yellow"]
15
+ green = [m for m, v in evaluation.items() if v.get("status") == "green"]
16
+ lines = [f"- Green: {len(green)}, Yellow: {len(yellow)}, Red: {len(red)}"]
17
+ if red:
18
+ lines.append(f"- Red flags: {', '.join(red)}")
19
+ if yellow:
20
+ lines.append(f"- Watch items: {', '.join(yellow)}")
21
+ lines.append("")
22
+ return lines
23
+
24
+
25
+ def _format_value(value: Any) -> str:
26
+ if isinstance(value, dict):
27
+ return json.dumps(value, ensure_ascii=False)
28
+ if isinstance(value, list):
29
+ return ", ".join(str(v) for v in value) or "—"
30
+ if value is None:
31
+ return "—"
32
+ return str(value)
33
+
34
+
35
+ def _render_metrics_group(title: str, group: dict[str, Any], confidence: dict[str, str]) -> list[str]:
36
+ lines = [f"## {title}", "", "| Metric | Value | Confidence |", "|--------|-------|------------|"]
37
+ for key, value in group.items():
38
+ conf = confidence.get(key, "exact")
39
+ lines.append(f"| `{key}` | {_format_value(value)} | {conf} |")
40
+ lines.append("")
41
+ return lines
42
+
43
+
44
+ def _render_evaluation(evaluation: dict[str, Any]) -> list[str]:
45
+ if not evaluation:
46
+ return []
47
+ lines = ["## Threshold Evaluation", "", "| Metric | Value | Status |", "|--------|-------|--------|"]
48
+ for metric, result in evaluation.items():
49
+ status = result.get("status", "unknown")
50
+ lines.append(f"| `{metric}` | {result.get('value')} | {status} |")
51
+ lines.append("")
52
+ return lines
53
+
54
+
55
+ def _generate_recommendations(
56
+ metrics: dict[str, Any], evaluation: dict[str, Any]
57
+ ) -> list[str]:
58
+ recs: list[str] = []
59
+ session = metrics.get("session", {})
60
+ workflow = metrics.get("workflow", {})
61
+ quality = metrics.get("quality", {})
62
+
63
+ if evaluation.get("retry_count", {}).get("status") == "red":
64
+ recs.append("High retry count detected; investigate prompt stability or environment flakiness.")
65
+ if evaluation.get("test_runs", {}).get("status") == "red":
66
+ recs.append("Few test runs recorded; ensure TDD red/green/refactor loop is visible in trace.")
67
+ if evaluation.get("pr_size", {}).get("status") == "red":
68
+ recs.append("PR size is large; consider splitting the change into smaller reviewable units.")
69
+ if workflow.get("stage_rework_count", 0) > 2:
70
+ recs.append("Frequent stage rework detected; clarify exit criteria before progressing.")
71
+ if quality.get("static_check_pass") is False:
72
+ recs.append("Static checks failed; fix lint/type/test issues before handoff.")
73
+ if session.get("error_count", 0) > 5:
74
+ recs.append("Elevated tool error count; review recent failures for systemic issues.")
75
+ return recs
76
+
77
+
78
+ def _render_recommendations(metrics: dict[str, Any], evaluation: dict[str, Any]) -> list[str]:
79
+ lines = ["## Recommendations", ""]
80
+ recs = _generate_recommendations(metrics, evaluation)
81
+ if recs:
82
+ for rec in recs:
83
+ lines.append(f"- {rec}")
84
+ else:
85
+ lines.append("- No automated recommendations.")
86
+ lines.append("")
87
+ return lines
88
+
89
+
90
+ def _render_data_sources(trace_files: list[str]) -> list[str]:
91
+ lines = ["## Data Sources", ""]
92
+ for tf in trace_files:
93
+ lines.append(f"- `{tf}`")
94
+ lines.append("")
95
+ return lines
96
+
97
+
98
+ def build_markdown_report(
99
+ report_id: str,
100
+ scenario: str,
101
+ trigger: str,
102
+ metrics: dict[str, Any],
103
+ confidence: dict[str, str],
104
+ evaluation: dict[str, Any],
105
+ state: dict[str, Any],
106
+ trace_files: list[str],
107
+ generated_at: str,
108
+ ) -> str:
109
+ """Render a benchmark report as Markdown."""
110
+ run = state.get("current_run", {})
111
+ lines = [
112
+ "# Lincoln Benchmark Report",
113
+ "",
114
+ f"- **Report ID:** `{report_id}`",
115
+ f"- **Scenario:** `{scenario}`",
116
+ f"- **Trigger:** `{trigger}`",
117
+ f"- **Generated at:** {generated_at}",
118
+ f"- **Process:** {run.get('variables', {}).get('process_slug', 'unknown')}",
119
+ f"- **Current stage:** {run.get('current_stage', 'unknown')}",
120
+ f"- **Workflow template:** {state.get('workflow', {}).get('template', 'unknown')}",
121
+ "",
122
+ "## Executive Summary",
123
+ "",
124
+ ]
125
+
126
+ lines.extend(_render_summary(evaluation))
127
+
128
+ for title, group_key in [
129
+ ("L1 Session Activity", "session"),
130
+ ("L2 Workflow Progress", "workflow"),
131
+ ("L3 Human-AI Collaboration", "collaboration"),
132
+ ("L4 Output Quality", "quality"),
133
+ ("L5 Business Outcome", "outcome"),
134
+ ]:
135
+ lines.extend(_render_metrics_group(title, metrics.get(group_key, {}), confidence))
136
+
137
+ lines.extend(_render_evaluation(evaluation))
138
+ lines.extend(_render_recommendations(metrics, evaluation))
139
+ lines.extend(_render_data_sources(trace_files))
140
+
141
+ return "\n".join(lines)
@@ -0,0 +1,289 @@
1
+ #!/usr/bin/env python3
2
+ """Auto-maintain the Lincoln /lc-* command surface.
3
+
4
+ Usage:
5
+ python3 scripts/lincoln_command_map.py --refresh
6
+ python3 scripts/lincoln_command_map.py --check
7
+
8
+ --refresh regenerates `.claude/harnesses/command-map.yaml` and syncs
9
+ `.claude-plugin/plugin.json` from the current on-disk skill/agent/workflow
10
+ facts. Static lifecycle commands are preserved.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import argparse
16
+ import json
17
+ import re
18
+ import sys
19
+ from pathlib import Path
20
+ from typing import Any
21
+
22
+ import yaml
23
+
24
+ sys.path.insert(0, str(Path(__file__).resolve().parent))
25
+
26
+ from lincoln_paths import ( # noqa: E402
27
+ PROJECT_ROOT,
28
+ atomic_write_text,
29
+ validate_name,
30
+ )
31
+
32
+ COMMAND_MAP_PATH = PROJECT_ROOT / ".claude" / "harnesses" / "command-map.yaml"
33
+ SCENARIOS_PATH = PROJECT_ROOT / ".claude" / "harnesses" / "scenarios.yaml"
34
+ PLUGIN_PATH = PROJECT_ROOT / ".claude-plugin" / "plugin.json"
35
+ WORKFLOWS_DIR = PROJECT_ROOT / ".claude" / "workflows"
36
+ AGENTS_DIR = PROJECT_ROOT / ".claude" / "agents"
37
+ SKILLS_DIR = PROJECT_ROOT / ".claude" / "skills"
38
+
39
+ # Lifecycle commands that are hand-maintained and must never be overwritten.
40
+ STATIC_COMMANDS = {
41
+ "lc-status",
42
+ "lc-setup",
43
+ "lc-init-branch",
44
+ "lc-validate",
45
+ "lc-handoff",
46
+ "lc-submit",
47
+ "lc-approve",
48
+ "lc-benchmark",
49
+ "lc-wf-list",
50
+ }
51
+
52
+ HEADER = """# lc-* 命令单一事实源(Single source of truth)
53
+ # 三个 harness manifest(claude-code.yaml / codex.yaml / opencode.yaml)通过
54
+ # command_map_source: command-map.yaml 引用本文件。
55
+ # 新增/修改命令请运行: python3 "$LINCOLN_ROOT/scripts/lincoln_command_map.py" --refresh
56
+ """
57
+
58
+ FRONTMATTER_RE = re.compile(r"\A---\n(.*?)\n---\n", re.DOTALL)
59
+
60
+
61
+ def load_yaml(path: Path) -> dict[str, Any]:
62
+ return yaml.safe_load(path.read_text(encoding="utf-8")) or {}
63
+
64
+
65
+ def load_command_map() -> dict[str, Any]:
66
+ if not COMMAND_MAP_PATH.exists():
67
+ return {}
68
+ return load_yaml(COMMAND_MAP_PATH)
69
+
70
+
71
+ def load_scenarios() -> dict[str, Any]:
72
+ if not SCENARIOS_PATH.exists():
73
+ return {}
74
+ return load_yaml(SCENARIOS_PATH).get("scenarios", {})
75
+
76
+
77
+ def _clean_name(value: str, kind: str) -> str:
78
+ """Validate an identifier before embedding it into commands or paths."""
79
+ return validate_name(value, kind)
80
+
81
+
82
+ def _iter_skill_dirs():
83
+ """Yield skill directories that contain a SKILL.md manifest."""
84
+ for path in sorted(SKILLS_DIR.iterdir()):
85
+ if not path.is_dir():
86
+ continue
87
+ if not (path / "SKILL.md").exists():
88
+ continue
89
+ yield path
90
+
91
+
92
+ def list_workflows() -> dict[str, dict[str, Any]]:
93
+ workflows: dict[str, dict[str, Any]] = {}
94
+ for path in sorted(WORKFLOWS_DIR.glob("*.yaml")):
95
+ data = load_yaml(path)
96
+ wf = data.get("workflow", {}) if isinstance(data, dict) else {}
97
+ stem = _clean_name(path.stem, "workflow name")
98
+ workflows[stem] = {
99
+ "name": wf.get("name", path.stem),
100
+ "description": wf.get("description", ""),
101
+ "execution_mode": wf.get("execution_mode", "team"),
102
+ }
103
+ return workflows
104
+
105
+
106
+ def list_agents() -> dict[str, dict[str, Any]]:
107
+ agents: dict[str, dict[str, Any]] = {}
108
+ excluded = {"default.md", "_contract.md"}
109
+ for path in sorted(AGENTS_DIR.glob("*.md")):
110
+ if path.name in excluded:
111
+ continue
112
+ front, _ = split_frontmatter(path.read_text(encoding="utf-8"))
113
+ stem = _clean_name(path.stem, "agent name")
114
+ agents[stem] = {
115
+ "name": front.get("name", path.stem),
116
+ "description": front.get("description", ""),
117
+ }
118
+ return agents
119
+
120
+
121
+ def list_skills() -> dict[str, dict[str, Any]]:
122
+ skills: dict[str, dict[str, Any]] = {}
123
+ for path in _iter_skill_dirs():
124
+ front, _ = split_frontmatter((path / "SKILL.md").read_text(encoding="utf-8"))
125
+ folder = _clean_name(path.name, "skill folder name")
126
+ skills[folder] = {
127
+ "name": front.get("name", path.name),
128
+ "description": front.get("description", ""),
129
+ }
130
+ return skills
131
+
132
+
133
+ def split_frontmatter(text: str) -> tuple[dict[str, Any], str]:
134
+ match = FRONTMATTER_RE.match(text)
135
+ if not match:
136
+ return {}, text
137
+ try:
138
+ front = yaml.safe_load(match.group(1)) or {}
139
+ except yaml.YAMLError:
140
+ front = {}
141
+ if not isinstance(front, dict):
142
+ front = {}
143
+ body_start = match.end()
144
+ return front, text[body_start:].lstrip("\n")
145
+
146
+
147
+ def _skill_command_key(folder: str) -> str:
148
+ """Avoid lc-skill-lc-* duplication by stripping a leading lc- prefix."""
149
+ return f"lc-skill-{folder.removeprefix('lc-')}"
150
+
151
+
152
+ def build_commands() -> dict[str, dict[str, Any]]:
153
+ existing = load_command_map().get("commands", {})
154
+ commands: dict[str, dict[str, Any]] = {}
155
+
156
+ # 1. Preserve static commands exactly as they are.
157
+ missing_static = []
158
+ for key in STATIC_COMMANDS:
159
+ if key in existing:
160
+ commands[key] = existing[key]
161
+ else:
162
+ missing_static.append(key)
163
+ if missing_static:
164
+ print(
165
+ f"WARNING: static commands missing from existing map: {', '.join(missing_static)}",
166
+ file=sys.stderr,
167
+ )
168
+
169
+ # 2. Workflow commands.
170
+ for stem, wf in list_workflows().items():
171
+ key = f"lc-wf-{stem}"
172
+ if key in STATIC_COMMANDS:
173
+ continue
174
+ if wf["execution_mode"] == "team":
175
+ args_hint = f"start --workflow {stem} --issue-number <N>"
176
+ else:
177
+ args_hint = f"start --workflow {stem}"
178
+ commands[key] = {
179
+ "description": wf["description"] or f"启动 {stem} 工作流",
180
+ "action": 'python3 "$LINCOLN_ROOT/scripts/lincoln_workflow.py"',
181
+ "args_hint": args_hint,
182
+ }
183
+
184
+ # 3. Agent commands.
185
+ for stem, agent in list_agents().items():
186
+ key = f"lc-agent-{stem}"
187
+ if key in STATIC_COMMANDS:
188
+ continue
189
+ commands[key] = {
190
+ "description": agent["description"] or f"调用 {stem} 角色",
191
+ "action": f'python3 "$LINCOLN_ROOT/scripts/lincoln_role.py" --role {stem}',
192
+ "args_hint": "$ARGUMENTS",
193
+ }
194
+
195
+ # 4. Skill commands.
196
+ for folder, skill in list_skills().items():
197
+ key = _skill_command_key(folder)
198
+ if key in STATIC_COMMANDS:
199
+ continue
200
+ commands[key] = {
201
+ "description": skill["description"] or f"调用 {folder} 技能",
202
+ "action": f'python3 "$LINCOLN_ROOT/scripts/lincoln_skill_prompt.py" --skill {folder}',
203
+ "args_hint": "$ARGUMENTS",
204
+ }
205
+
206
+ # 5. Scenario commands.
207
+ for sid, scenario in load_scenarios().items():
208
+ sid = _clean_name(sid, "scenario id")
209
+ key = f"lc-scenario-{sid}"
210
+ if key in STATIC_COMMANDS:
211
+ continue
212
+ commands[key] = {
213
+ "description": scenario.get("description", f"场景: {sid}"),
214
+ "action": f'python3 "$LINCOLN_ROOT/scripts/lincoln_scenario.py" --scenario {sid}',
215
+ "args_hint": "$ARGUMENTS",
216
+ }
217
+
218
+ return dict(sorted(commands.items()))
219
+
220
+
221
+ def refresh_command_map() -> None:
222
+ commands = build_commands()
223
+ data = {"commands": commands}
224
+ atomic_write_text(
225
+ COMMAND_MAP_PATH,
226
+ HEADER + yaml.safe_dump(data, allow_unicode=True, sort_keys=False),
227
+ encoding="utf-8",
228
+ )
229
+ print(f"Updated {COMMAND_MAP_PATH.relative_to(PROJECT_ROOT)} ({len(commands)} commands)")
230
+
231
+
232
+ def refresh_plugin_json() -> None:
233
+ if not PLUGIN_PATH.exists():
234
+ raise SystemExit(f"ERROR: plugin.json not found: {PLUGIN_PATH}")
235
+ plugin = json.loads(PLUGIN_PATH.read_text(encoding="utf-8"))
236
+
237
+ skill_paths = [f"./.claude/skills/{path.name}/" for path in _iter_skill_dirs()]
238
+
239
+ plugin["skills"] = skill_paths
240
+ atomic_write_text(
241
+ PLUGIN_PATH,
242
+ json.dumps(plugin, indent=2, ensure_ascii=False) + "\n",
243
+ encoding="utf-8",
244
+ )
245
+ print(f"Updated {PLUGIN_PATH.relative_to(PROJECT_ROOT)} ({len(skill_paths)} skills)")
246
+
247
+
248
+ def check() -> int:
249
+ commands = build_commands()
250
+ existing = load_command_map().get("commands", {})
251
+ missing = set(commands) - set(existing)
252
+ extra = set(existing) - set(commands)
253
+ changed: list[str] = []
254
+ for key in set(commands) & set(existing):
255
+ if commands[key] != existing[key]:
256
+ changed.append(key)
257
+ if not (missing or extra or changed):
258
+ print("command-map.yaml is up to date.")
259
+ return 0
260
+ if missing:
261
+ print("Missing commands:", ", ".join(sorted(missing)))
262
+ if extra:
263
+ print("Extra commands:", ", ".join(sorted(extra)))
264
+ if changed:
265
+ print("Changed commands:", ", ".join(sorted(changed)))
266
+ try:
267
+ script_rel = Path(__file__).relative_to(PROJECT_ROOT)
268
+ except ValueError:
269
+ script_rel = Path("scripts/lincoln_command_map.py")
270
+ print(f"Run: python3 {script_rel} --refresh")
271
+ return 1
272
+
273
+
274
+ def main() -> int:
275
+ parser = argparse.ArgumentParser(description="Maintain Lincoln /lc-* command surface")
276
+ group = parser.add_mutually_exclusive_group(required=True)
277
+ group.add_argument("--refresh", action="store_true", help="Regenerate command-map.yaml and plugin.json")
278
+ group.add_argument("--check", action="store_true", help="Check if command-map.yaml is in sync")
279
+ args = parser.parse_args()
280
+
281
+ if args.refresh:
282
+ refresh_command_map()
283
+ refresh_plugin_json()
284
+ return 0
285
+ return check()
286
+
287
+
288
+ if __name__ == "__main__":
289
+ sys.exit(main())