@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,356 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5
+ cd "$ROOT"
6
+
7
+ STATIC_CHECK_RESULT="$ROOT/.context/static-check-result.json"
8
+ mkdir -p "$ROOT/.context"
9
+
10
+ # Prefer project venv if available; otherwise rely on system python3 having pytest/pyyaml.
11
+ if [ -d "$ROOT/.venv" ] && [ -x "$ROOT/.venv/bin/python3" ]; then
12
+ PYTHON="$ROOT/.venv/bin/python3"
13
+ elif [ -d "$ROOT/venv" ] && [ -x "$ROOT/venv/bin/python3" ]; then
14
+ PYTHON="$ROOT/venv/bin/python3"
15
+ else
16
+ PYTHON="python3"
17
+ fi
18
+
19
+ # Record a structured pass/fail result so benchmark metrics can consume it
20
+ # instead of regex-scanning the command text.
21
+ write_static_check_result() {
22
+ local passed="$1"
23
+ "$PYTHON" - "$passed" <<'PY'
24
+ import sys, json
25
+ from datetime import datetime, timezone
26
+ passed = sys.argv[1] == "true"
27
+ print(json.dumps({
28
+ "passed": passed,
29
+ "timestamp": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
30
+ }, ensure_ascii=False))
31
+ PY
32
+ }
33
+
34
+ trap 'write_static_check_result false > "$STATIC_CHECK_RESULT"' ERR
35
+
36
+ echo "==> Validate workflow YAML"
37
+ "$PYTHON" -c "import yaml; yaml.safe_load(open('.claude/workflows/interview-to-knowledge.yaml'))"
38
+
39
+ echo "==> Validate skill manifests"
40
+ for skill in .claude/skills/*/SKILL.md; do
41
+ [ -f "$skill" ] || continue
42
+ "$PYTHON" - "$skill" <<'PY'
43
+ import sys, yaml
44
+ path = sys.argv[1]
45
+ text = open(path, encoding="utf-8").read()
46
+ if text.startswith("---"):
47
+ end = text.find("---", 3)
48
+ if end != -1:
49
+ frontmatter = text[3:end]
50
+ try:
51
+ yaml.safe_load(frontmatter)
52
+ except Exception as exc:
53
+ print(f"Invalid frontmatter in {path}: {exc}")
54
+ sys.exit(1)
55
+ print(f"OK: {path}")
56
+ PY
57
+ if [ $? -ne 0 ]; then
58
+ exit 1
59
+ fi
60
+ done
61
+
62
+ echo "==> Validate skill dependency manifest"
63
+ DEP_FILE=".claude/skills/dependencies.yaml"
64
+ if [ ! -f "$DEP_FILE" ]; then
65
+ DEP_FILE=".claude/skill-dependencies.yaml"
66
+ fi
67
+ "$PYTHON" -c "import yaml; yaml.safe_load(open('$DEP_FILE'))"
68
+
69
+ if [ -x "scripts/check-skill-dependencies.sh" ]; then
70
+ echo "==> Check skill dependencies (non-blocking)"
71
+ bash scripts/check-skill-dependencies.sh || true
72
+ fi
73
+
74
+ echo "==> Validate workflow templates reference stage YAMLs"
75
+ "$PYTHON" - "$ROOT" <<'PY'
76
+ import sys
77
+ from pathlib import Path
78
+ import yaml
79
+
80
+ root = Path(sys.argv[1])
81
+ templates_dir = root / ".claude" / "workflows" / "templates"
82
+ main_workflow = root / ".claude" / "workflows" / "interview-to-knowledge.yaml"
83
+ errors = []
84
+
85
+ for path in list(templates_dir.glob("*.yaml")) + [main_workflow]:
86
+ if not path.exists():
87
+ continue
88
+ try:
89
+ data = yaml.safe_load(path.read_text(encoding="utf-8"))
90
+ except Exception as exc:
91
+ errors.append(f"{path.name}: YAML parse error: {exc}")
92
+ continue
93
+ workflow = data.get("workflow", data)
94
+ for step in workflow.get("steps", []):
95
+ stage_id = step.get("id")
96
+ if not stage_id:
97
+ errors.append(f"{path.name}: step missing id")
98
+ continue
99
+ stage_yaml = root / ".claude" / "stages" / f"{stage_id}.yaml"
100
+ if not stage_yaml.exists():
101
+ errors.append(f"{path.name}: missing stage YAML {stage_yaml}")
102
+
103
+ if errors:
104
+ print("Workflow template issues:")
105
+ for e in errors:
106
+ print(f" - {e}")
107
+ sys.exit(1)
108
+
109
+ print("All workflow templates reference valid stage YAMLs.")
110
+ PY
111
+
112
+ echo "==> Validate JSON schemas are valid JSON"
113
+ "$PYTHON" - "$ROOT" <<'PY'
114
+ import sys, json
115
+ from pathlib import Path
116
+ root = Path(sys.argv[1])
117
+ errors = []
118
+ for schema_path in (root / ".claude" / "schemas").glob("*.json"):
119
+ try:
120
+ json.loads(schema_path.read_text(encoding="utf-8"))
121
+ except Exception as exc:
122
+ errors.append(f"{schema_path.name}: {exc}")
123
+ if errors:
124
+ print("Invalid JSON schemas:")
125
+ for e in errors:
126
+ print(f" - {e}")
127
+ sys.exit(1)
128
+ print("All JSON schemas are valid.")
129
+ PY
130
+
131
+ echo "==> Validate agent frontmatters"
132
+ "$PYTHON" - "$ROOT" <<'PY'
133
+ import sys, yaml
134
+ from pathlib import Path
135
+
136
+ root = Path(sys.argv[1])
137
+ errors = []
138
+ for agent_md in (root / ".claude" / "agents").glob("*.md"):
139
+ text = agent_md.read_text(encoding="utf-8")
140
+ if not text.startswith("---"):
141
+ errors.append(f"{agent_md.name}: missing frontmatter")
142
+ continue
143
+ end = text.find("---", 3)
144
+ if end == -1:
145
+ errors.append(f"{agent_md.name}: unterminated frontmatter")
146
+ continue
147
+ try:
148
+ fm = yaml.safe_load(text[3:end])
149
+ except Exception as exc:
150
+ errors.append(f"{agent_md.name}: invalid frontmatter: {exc}")
151
+ continue
152
+ if not isinstance(fm, dict):
153
+ errors.append(f"{agent_md.name}: frontmatter is not a mapping")
154
+ continue
155
+ for key in ["name", "description"]:
156
+ if key not in fm:
157
+ errors.append(f"{agent_md.name}: missing {key}")
158
+ if errors:
159
+ print("Agent frontmatter issues:")
160
+ for e in errors:
161
+ print(f" - {e}")
162
+ sys.exit(1)
163
+ print("All agent frontmatters valid.")
164
+ PY
165
+
166
+ echo "==> Validate Python syntax"
167
+ "$PYTHON" -m py_compile scripts/validate_stage.py
168
+
169
+ echo "==> Validate prompt paths in skills"
170
+ "$PYTHON" - "$ROOT" <<'PY'
171
+ import sys
172
+ from pathlib import Path
173
+
174
+ root = Path(sys.argv[1])
175
+ missing = []
176
+ for skill_dir in (root / ".claude" / "skills").iterdir():
177
+ if not skill_dir.is_dir():
178
+ continue
179
+ skill_md = skill_dir / "SKILL.md"
180
+ if not skill_md.exists():
181
+ continue
182
+ text = skill_md.read_text(encoding="utf-8")
183
+ # Only enforce prompts/main.md when the skill explicitly declares it as entry
184
+ if "prompts/main.md" not in text:
185
+ continue
186
+ main_prompt = skill_dir / "prompts" / "main.md"
187
+ if not main_prompt.exists():
188
+ missing.append(str(main_prompt))
189
+ if missing:
190
+ print("Missing prompts:")
191
+ for m in missing:
192
+ print(f" - {m}")
193
+ sys.exit(1)
194
+ print("All prompt paths resolved.")
195
+ PY
196
+
197
+ echo "==> Validate workflow-stage.yaml schema"
198
+ "$PYTHON" - "$ROOT" <<'PY'
199
+ import sys
200
+ from pathlib import Path
201
+ import yaml
202
+
203
+ root = Path(sys.argv[1])
204
+ state_file = root / ".claude" / "workflow-stage.yaml"
205
+ legacy_state_file = root / ".claude" / "workflow-state.yaml"
206
+ if not state_file.exists() and legacy_state_file.exists():
207
+ state_file = legacy_state_file
208
+
209
+ if not state_file.exists():
210
+ print("workflow-stage.yaml not found; skipping")
211
+ sys.exit(0)
212
+
213
+ state = yaml.safe_load(state_file.read_text(encoding="utf-8"))
214
+ required_top_legacy = ["schema_version", "workflow", "current_run", "stages", "recovery"]
215
+ required_top_new = ["schema_version", "workflow", "current_run", "nodes", "recovery"]
216
+ if "nodes" in state:
217
+ missing = [k for k in required_top_new if k not in state]
218
+ elif "stages" in state:
219
+ missing = [k for k in required_top_legacy if k not in state]
220
+ else:
221
+ missing = [k for k in required_top_new if k not in state]
222
+ if missing:
223
+ print(f"Missing top-level keys: {', '.join(missing)}")
224
+ sys.exit(1)
225
+
226
+ print("workflow-stage.yaml schema valid.")
227
+ PY
228
+
229
+ echo "==> Validate stage YAML files"
230
+ "$PYTHON" - "$ROOT" <<'PY'
231
+ import sys
232
+ from pathlib import Path
233
+ import yaml
234
+
235
+ root = Path(sys.argv[1])
236
+ errors = []
237
+ for stage_yaml in sorted((root / ".claude" / "stages").glob("*.yaml")):
238
+ if stage_yaml.name == "stage-manifest.yaml":
239
+ continue
240
+ try:
241
+ data = yaml.safe_load(stage_yaml.read_text(encoding="utf-8"))
242
+ except Exception as exc:
243
+ errors.append(f"{stage_yaml.name}: YAML parse error: {exc}")
244
+ continue
245
+ if not isinstance(data, dict):
246
+ errors.append(f"{stage_yaml.name}: root is not a mapping")
247
+ continue
248
+ for key in ["schema_version", "id", "name", "description", "templates", "prerequisite_stage", "next_stage", "human_gate", "agent", "skills", "artifacts", "context", "gates"]:
249
+ if key not in data:
250
+ errors.append(f"{stage_yaml.name}: missing key '{key}'")
251
+
252
+ if errors:
253
+ print("Stage YAML issues:")
254
+ for e in errors:
255
+ print(f" - {e}")
256
+ sys.exit(1)
257
+ print("All stage YAML files valid.")
258
+ PY
259
+
260
+ echo "==> Validate stage YAML files against schema"
261
+ "$PYTHON" - "$ROOT" <<'PY'
262
+ import sys
263
+ from pathlib import Path
264
+ import yaml
265
+ import json
266
+
267
+ root = Path(sys.argv[1])
268
+ schema_path = root / ".claude" / "schemas" / "stage-definition.schema.json"
269
+ schema = json.loads(schema_path.read_text(encoding="utf-8"))
270
+
271
+ # Minimal structural validation
272
+ required = set(schema.get("required", []))
273
+ errors = []
274
+ for stage_yaml in sorted((root / ".claude" / "stages").glob("*.yaml")):
275
+ if stage_yaml.name == "stage-manifest.yaml":
276
+ continue
277
+ try:
278
+ data = yaml.safe_load(stage_yaml.read_text(encoding="utf-8"))
279
+ except Exception as exc:
280
+ errors.append(f"{stage_yaml.name}: YAML parse error: {exc}")
281
+ continue
282
+ missing = required - set(data.keys())
283
+ if missing:
284
+ errors.append(f"{stage_yaml.name}: missing required keys: {', '.join(sorted(missing))}")
285
+
286
+ if errors:
287
+ print("Stage schema issues:")
288
+ for e in errors:
289
+ print(f" - {e}")
290
+ sys.exit(1)
291
+ print("All stage YAML files match required schema.")
292
+ PY
293
+
294
+ echo "==> Validate hook scripts are executable"
295
+ for hook in "$ROOT/.claude/hooks/"*.sh; do
296
+ if [ -f "$hook" ] && [ ! -x "$hook" ]; then
297
+ echo "Hook not executable: $hook"
298
+ exit 1
299
+ fi
300
+ done
301
+ echo "All hooks executable."
302
+
303
+ echo "==> Validate Python syntax for scripts"
304
+ # Compile every Python script under scripts/ (skip __pycache__ and non-.py files)
305
+ py_errors=0
306
+ for pyfile in scripts/*.py; do
307
+ [ -f "$pyfile" ] || continue
308
+ if ! "$PYTHON" -m py_compile "$pyfile"; then
309
+ py_errors=$((py_errors + 1))
310
+ fi
311
+ done
312
+ if [ $py_errors -ne 0 ]; then
313
+ echo "Python syntax errors detected: $py_errors"
314
+ exit 1
315
+ fi
316
+
317
+ echo "==> Check command-map drift"
318
+ "$PYTHON" scripts/lincoln_command_map.py --check
319
+
320
+ echo "==> Check main merge hygiene"
321
+ "$PYTHON" scripts/check-main-merge-hygiene.py || true
322
+
323
+ echo "==> Validate bash syntax for scripts"
324
+ bash -n scripts/init-lincoln-branch.sh
325
+ bash -n scripts/init-project.sh
326
+ bash -n scripts/list-active-lincoln-branches.sh
327
+ bash -n scripts/check-skill-dependencies.sh
328
+ bash -n scripts/sync-external-agents.sh
329
+ bash -n scripts/check-harness-drift.sh
330
+ for hook in "$ROOT/.claude/hooks/"*.sh; do
331
+ bash -n "$hook"
332
+ done
333
+
334
+ echo "==> Check harness drift"
335
+ bash scripts/check-harness-drift.sh
336
+
337
+ echo "==> Check version lockstep"
338
+ "$PYTHON" scripts/bump_version.py --check
339
+
340
+ echo "==> Check plugin package manifest"
341
+ find .claude scripts tools -type d -name __pycache__ -prune -exec rm -rf {} + 2>/dev/null || true
342
+ "$PYTHON" scripts/package-lincoln-plugin.py check
343
+
344
+ echo "==> Run pytest"
345
+ "$PYTHON" -m pytest tests/ -v
346
+ pytest_exit=$?
347
+
348
+ if [ $pytest_exit -eq 0 ]; then
349
+ write_static_check_result true > "$STATIC_CHECK_RESULT"
350
+ echo "==> All static checks passed"
351
+ else
352
+ write_static_check_result false > "$STATIC_CHECK_RESULT"
353
+ echo "==> Static checks failed"
354
+ fi
355
+
356
+ exit $pytest_exit
@@ -0,0 +1,210 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # Sync external agent definitions declared by .claude/agents/external/*.manifest.yaml.
5
+ # Usage:
6
+ # scripts/sync-external-agents.sh
7
+ # scripts/sync-external-agents.sh --dry-run
8
+
9
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
10
+ ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
11
+ cd "$ROOT"
12
+
13
+ DRY_RUN=false
14
+ if [[ "${1:-}" == "--dry-run" ]]; then
15
+ DRY_RUN=true
16
+ fi
17
+
18
+ AGENTS_DIR="$ROOT/.claude/agents/external"
19
+ mkdir -p "$AGENTS_DIR"
20
+
21
+ "$ROOT/.venv/bin/python3" - "$AGENTS_DIR" "$DRY_RUN" <<'PY'
22
+ import sys
23
+ from pathlib import Path
24
+ import re
25
+ import shutil
26
+ import subprocess
27
+ import yaml
28
+
29
+ agents_dir = Path(sys.argv[1])
30
+ dry_run = sys.argv[2].lower() == "true"
31
+
32
+ KNOWN_FIELDS = {"name", "description", "extends", "model", "tools", "disallowed_tools"}
33
+ PERMISSIVE_LICENSES = {"mit", "apache-2.0", "bsd-3-clause", "bsd-2-clause", "isc"}
34
+
35
+
36
+ def slugify(value: str) -> str:
37
+ value = re.sub(r"[^\w\s-]", "", value).strip().lower()
38
+ return re.sub(r"[-\s]+", "-", value)
39
+
40
+
41
+ def normalize_frontmatter(text: str, prefix: str, source: str, ref: str, license_key: str, original_name: str) -> str:
42
+ if not text.startswith("---"):
43
+ return text
44
+ parts = text.split("---", 2)
45
+ if len(parts) < 3:
46
+ return text
47
+ try:
48
+ front = yaml.safe_load(parts[1]) or {}
49
+ except yaml.YAMLError:
50
+ return text
51
+
52
+ if not isinstance(front, dict):
53
+ front = {}
54
+
55
+ normalized = {k: v for k, v in front.items() if k in KNOWN_FIELDS}
56
+
57
+ # Prefix the agent name to avoid collisions.
58
+ normalized["name"] = f"{prefix}-{slugify(original_name)}"
59
+ normalized["original_name"] = original_name
60
+ normalized["source"] = source
61
+ normalized["ref"] = ref
62
+ normalized["license"] = license_key
63
+
64
+ # Map camelCase / legacy fields.
65
+ if "disallowedTools" in front and "disallowed_tools" not in normalized:
66
+ normalized["disallowed_tools"] = front["disallowedTools"]
67
+
68
+ # Resolve inherited models.
69
+ model = normalized.get("model")
70
+ if isinstance(model, str):
71
+ model = model.lower().strip()
72
+ if model in {"inherit", "default", "auto"}:
73
+ normalized["model"] = "sonnet"
74
+ if "model" not in normalized:
75
+ normalized["model"] = "sonnet"
76
+
77
+ # Remove extends from imported standalone agents; Lincoln wrappers handle composition.
78
+ normalized.pop("extends", None)
79
+
80
+ normalized_yaml = yaml.safe_dump(normalized, sort_keys=False, allow_unicode=True)
81
+ attribution = (
82
+ f"<!-- Imported from {source} @ {ref}, licensed under {license_key}. "
83
+ f"Original name: {original_name}. -->"
84
+ )
85
+ body = parts[2].lstrip("\n")
86
+ return f"---\n{normalized_yaml}---\n\n{attribution}\n\n{body}"
87
+
88
+
89
+ def parse_manifest(manifest_path: Path) -> dict | None:
90
+ docs = list(yaml.safe_load_all(manifest_path.read_text(encoding="utf-8")))
91
+ data = docs[0] if docs else None
92
+ if not isinstance(data, dict):
93
+ print(f"Skipping {manifest_path.name}: invalid manifest")
94
+ return None
95
+ return data
96
+
97
+
98
+ def agent_source_path(agents_subdir: str, imported: str) -> str:
99
+ if imported.endswith(".md"):
100
+ return f"{agents_subdir}/{imported}"
101
+ return f"{agents_subdir}/{imported}.md"
102
+
103
+
104
+ def agent_basename(imported: str) -> str:
105
+ name = imported[:-3] if imported.endswith(".md") else imported
106
+ return Path(name).name
107
+
108
+
109
+ notices = []
110
+ notices.append("# 外部 Agent 来源声明\n")
111
+ notices.append("本文件由 `scripts/sync-external-agents.sh` 自动生成,请勿手动修改。\n")
112
+ notices.append("| Lincoln 文件名 | 原始名称 | 来源仓库 | 引用 | 许可证 |")
113
+ notices.append("|---|---|---|---|---|")
114
+
115
+ for manifest_path in sorted(agents_dir.glob("*.manifest.yaml")):
116
+ data = parse_manifest(manifest_path)
117
+ if data is None:
118
+ continue
119
+
120
+ framework = manifest_path.stem.replace(".manifest", "")
121
+ source = data.get("source", "")
122
+ ref = data.get("ref", "main") or "main"
123
+ license_key = (data.get("license", "") or "").lower()
124
+ prefix = data.get("prefix", framework)
125
+ agents_subdir = data.get("paths", {}).get("agents", ".claude/agents")
126
+ imported_agents = data.get("imported_agents", [])
127
+
128
+ if not source:
129
+ print(f"Skipping {manifest_path.name}: no source declared")
130
+ continue
131
+ if license_key not in PERMISSIVE_LICENSES:
132
+ print(f"Skipping {manifest_path.name}: license '{license_key}' is not permissive")
133
+ continue
134
+ if not imported_agents:
135
+ print(f"Skipping {manifest_path.name}: no imported_agents")
136
+ continue
137
+
138
+ target_dir = agents_dir / framework / "agents"
139
+ print(f"Syncing {framework} from {source} @ {ref}")
140
+
141
+ if dry_run:
142
+ print(f" [dry-run] Would clone/sparse-checkout into {agents_dir / framework}")
143
+ for imported in imported_agents:
144
+ print(f" [dry-run] Would import {imported} as {prefix}-{slugify(agent_basename(imported))}")
145
+ continue
146
+
147
+ if target_dir.exists():
148
+ shutil.rmtree(target_dir.parent)
149
+ target_dir.mkdir(parents=True, exist_ok=True)
150
+
151
+ repo_dir = agents_dir / framework / ".repo"
152
+ if repo_dir.exists():
153
+ shutil.rmtree(repo_dir)
154
+ repo_dir.mkdir(parents=True, exist_ok=True)
155
+
156
+ sparse_paths = [agent_source_path(agents_subdir, imp) for imp in imported_agents]
157
+
158
+ try:
159
+ subprocess.run(
160
+ [
161
+ "git", "clone", "--depth", "1", "--branch", ref,
162
+ "--filter=blob:none", "--sparse", source, str(repo_dir),
163
+ ],
164
+ check=True,
165
+ capture_output=True,
166
+ )
167
+ subprocess.run(
168
+ ["git", "sparse-checkout", "set", "--no-cone", *sparse_paths],
169
+ cwd=repo_dir,
170
+ check=True,
171
+ capture_output=True,
172
+ )
173
+ except subprocess.CalledProcessError as exc:
174
+ print(f" Failed to sync {framework}: {exc}")
175
+ if exc.stderr:
176
+ print(exc.stderr.decode("utf-8", errors="replace"))
177
+ continue
178
+
179
+ # Copy and normalize each imported agent.
180
+ for imported in imported_agents:
181
+ src_rel = agent_source_path(agents_subdir, imported)
182
+ src_file = repo_dir / src_rel
183
+ original_name = agent_basename(imported)
184
+ normalized_name = f"{prefix}-{slugify(original_name)}"
185
+ dest_file = target_dir / f"{normalized_name}.md"
186
+
187
+ if not src_file.exists():
188
+ print(f" Warning: expected agent file not found: {src_rel}")
189
+ continue
190
+
191
+ raw_text = src_file.read_text(encoding="utf-8")
192
+ normalized_text = normalize_frontmatter(
193
+ raw_text, prefix, source, ref, license_key, original_name
194
+ )
195
+ dest_file.write_text(normalized_text, encoding="utf-8")
196
+ notices.append(
197
+ f"| {normalized_name}.md | {original_name} | {source} | {ref} | {license_key.upper()} |"
198
+ )
199
+ print(f" Imported {normalized_name}")
200
+
201
+ # Clean up the temporary clone.
202
+ shutil.rmtree(repo_dir)
203
+
204
+ # Write NOTICES.md
205
+ notices_path = agents_dir / "NOTICES.md"
206
+ notices_path.write_text("\n".join(notices) + "\n", encoding="utf-8")
207
+ print(f"Wrote {notices_path}")
208
+
209
+ print("External agent sync complete.")
210
+ PY