@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.
- package/dist/main.d.ts +3 -0
- package/dist/main.js +1231 -906
- package/dist/main.js.map +1 -1
- package/dist/postinstall.d.ts +3 -0
- package/dist/postinstall.js +18 -0
- package/dist/postinstall.js.map +1 -0
- package/framework/.claude/agents/_contract.md +79 -0
- package/framework/.claude/agents/architect.md +31 -0
- package/framework/.claude/agents/default.md +151 -0
- package/framework/.claude/agents/designer.md +33 -0
- package/framework/.claude/agents/engineer.md +42 -0
- package/framework/.claude/agents/external/NOTICES.md +12 -0
- package/framework/.claude/agents/external/everything-claude-code.manifest.yaml +23 -0
- package/framework/.claude/agents/external/oh-my-claudecode.manifest.yaml +26 -0
- package/framework/.claude/agents/external/wshobson-agents.manifest.yaml +23 -0
- package/framework/.claude/agents/frontend-engineer.md +32 -0
- package/framework/.claude/agents/knowledge-curator.md +28 -0
- package/framework/.claude/agents/pm.md +38 -0
- package/framework/.claude/agents/qa.md +28 -0
- package/framework/.claude/agents/release-coordinator.md +25 -0
- package/framework/.claude/agents/researcher.md +41 -0
- package/framework/.claude/harnesses/claude-code.yaml +15 -0
- package/framework/.claude/harnesses/codex.yaml +40 -0
- package/framework/.claude/harnesses/command-map.yaml +255 -0
- package/framework/.claude/harnesses/opencode.yaml +32 -0
- package/framework/.claude/harnesses/scenarios.yaml +45 -0
- package/framework/.claude/hooks/on-pr-event.sh +69 -0
- package/framework/.claude/hooks/on-session-start.sh +427 -0
- package/framework/.claude/hooks/on-stop.sh +104 -0
- package/framework/.claude/hooks/post-tool-use.sh +161 -0
- package/framework/.claude/hooks/pre-tool-use.sh +246 -0
- package/framework/.claude/schemas/agent-definition.schema.json +35 -0
- package/framework/.claude/schemas/benchmark-report.schema.json +148 -0
- package/framework/.claude/schemas/pm-to-ux-handoff.schema.yaml +128 -0
- package/framework/.claude/schemas/stage-definition.schema.json +233 -0
- package/framework/.claude/schemas/workflow-stage.schema.json +86 -0
- package/framework/.claude/schemas/workflow-template.schema.json +88 -0
- package/framework/.claude/settings.json +14 -0
- package/framework/.claude/skills/build-product-prototype/SKILL.md +35 -0
- package/framework/.claude/skills/build-product-prototype/prompts/main.md +78 -0
- package/framework/.claude/skills/clarify-requirements/SKILL.md +32 -0
- package/framework/.claude/skills/clarify-requirements/prompts/main.md +81 -0
- package/framework/.claude/skills/dependencies.yaml +139 -0
- package/framework/.claude/skills/draft-product-design/SKILL.md +40 -0
- package/framework/.claude/skills/draft-product-design/prompts/main.md +47 -0
- package/framework/.claude/skills/lc-analyze-frameworks/SKILL.md +43 -0
- package/framework/.claude/skills/lc-analyze-frameworks/prompts/main.md +95 -0
- package/framework/.claude/skills/lc-benchmark/SKILL.md +61 -0
- package/framework/.claude/skills/lc-build-codebase-knowledge/SKILL.md +38 -0
- package/framework/.claude/skills/lc-build-codebase-knowledge/prompts/build-codebase-knowledge.md +61 -0
- package/framework/.claude/skills/lc-collect-intelligence/SKILL.md +43 -0
- package/framework/.claude/skills/lc-collect-intelligence/prompts/main.md +72 -0
- package/framework/.claude/skills/lc-competitive-analysis/SKILL.md +43 -0
- package/framework/.claude/skills/lc-competitive-analysis/prompts/main.md +70 -0
- package/framework/.claude/skills/lc-explore-opensource/SKILL.md +36 -0
- package/framework/.claude/skills/lc-explore-opensource/prompts/explore-opensource.md +77 -0
- package/framework/.claude/skills/lc-first-principles/SKILL.md +43 -0
- package/framework/.claude/skills/lc-first-principles/prompts/main.md +73 -0
- package/framework/.claude/skills/lc-handoff/SKILL.md +34 -0
- package/framework/.claude/skills/lc-init-branch/SKILL.md +52 -0
- package/framework/.claude/skills/lc-market-research/SKILL.md +43 -0
- package/framework/.claude/skills/lc-market-research/prompts/main.md +79 -0
- package/framework/.claude/skills/lc-product-research/SKILL.md +43 -0
- package/framework/.claude/skills/lc-product-research/prompts/main.md +80 -0
- package/framework/.claude/skills/lc-research-report/SKILL.md +43 -0
- package/framework/.claude/skills/lc-research-report/prompts/main.md +90 -0
- package/framework/.claude/skills/lc-research-scope/SKILL.md +43 -0
- package/framework/.claude/skills/lc-research-scope/prompts/main.md +82 -0
- package/framework/.claude/skills/lc-setup/SKILL.md +68 -0
- package/framework/.claude/skills/lc-setup/prompts/main.md +88 -0
- package/framework/.claude/skills/lc-stage/SKILL.md +45 -0
- package/framework/.claude/skills/lc-stakeholder-research/SKILL.md +43 -0
- package/framework/.claude/skills/lc-stakeholder-research/prompts/main.md +65 -0
- package/framework/.claude/skills/lc-status/SKILL.md +25 -0
- package/framework/.claude/skills/lc-storytelling/SKILL.md +43 -0
- package/framework/.claude/skills/lc-storytelling/prompts/main.md +77 -0
- package/framework/.claude/skills/lc-wf/SKILL.md +54 -0
- package/framework/.claude/skills/lc-workflow/SKILL.md +48 -0
- package/framework/.claude/skills/lc-workflow/validators/validate.py +755 -0
- package/framework/.claude/skills/lc-workflow-router/SKILL.md +41 -0
- package/framework/.claude/skills/lc-workflow-router/prompts/intake-prompt.md +91 -0
- package/framework/.claude/skills/lc-workflow-router/prompts/router-prompt.md +44 -0
- package/framework/.claude/skills/plan-tdd-development/SKILL.md +31 -0
- package/framework/.claude/skills/plan-tdd-development/prompts/main.md +44 -0
- package/framework/.claude/skills/process-interview/SKILL.md +32 -0
- package/framework/.claude/skills/process-interview/prompts/main.md +47 -0
- package/framework/.claude/skills/propose-with-openspec/SKILL.md +37 -0
- package/framework/.claude/skills/propose-with-openspec/prompts/main.md +53 -0
- package/framework/.claude/skills/split-to-github/SKILL.md +32 -0
- package/framework/.claude/skills/split-to-github/prompts/main.md +42 -0
- package/framework/.claude/skills/sync-to-knowledge/SKILL.md +35 -0
- package/framework/.claude/skills/sync-to-knowledge/prompts/main.md +54 -0
- package/framework/.claude/skills/workflow-continue/SKILL.md +24 -0
- package/framework/.claude/skills/workflow-continue/prompts/main.md +25 -0
- package/framework/.claude/stages/build-codebase-knowledge.yaml +42 -0
- package/framework/.claude/stages/clarify.yaml +59 -0
- package/framework/.claude/stages/explore-opensource.yaml +40 -0
- package/framework/.claude/stages/implement.yaml +60 -0
- package/framework/.claude/stages/ingest.yaml +40 -0
- package/framework/.claude/stages/lc-analyze-frameworks.yaml +37 -0
- package/framework/.claude/stages/lc-collect-intelligence.yaml +37 -0
- package/framework/.claude/stages/lc-competitive-analysis.yaml +37 -0
- package/framework/.claude/stages/lc-first-principles.yaml +37 -0
- package/framework/.claude/stages/lc-market-research.yaml +37 -0
- package/framework/.claude/stages/lc-product-research.yaml +37 -0
- package/framework/.claude/stages/lc-research-report.yaml +38 -0
- package/framework/.claude/stages/lc-research-scope.yaml +38 -0
- package/framework/.claude/stages/lc-stakeholder-research.yaml +37 -0
- package/framework/.claude/stages/lc-storytelling.yaml +37 -0
- package/framework/.claude/stages/product-design-docs.yaml +66 -0
- package/framework/.claude/stages/product-prototype.yaml +53 -0
- package/framework/.claude/stages/propose.yaml +45 -0
- package/framework/.claude/stages/split.yaml +41 -0
- package/framework/.claude/stages/sync-knowledge.yaml +49 -0
- package/framework/.claude/stages/tdd-development-plan.yaml +43 -0
- package/framework/.claude/stages/workflow-router.yaml +45 -0
- package/framework/.claude/templates/solo-workflow-context.yaml +23 -0
- package/framework/.claude/workflows/README.md +93 -0
- package/framework/.claude/workflows/bug-fix.yaml +81 -0
- package/framework/.claude/workflows/design-spike.yaml +55 -0
- package/framework/.claude/workflows/existing-project-iteration.yaml +106 -0
- package/framework/.claude/workflows/interview-to-knowledge.yaml +189 -0
- package/framework/.claude/workflows/oss-first-design.yaml +100 -0
- package/framework/.claude/workflows/pm-research.yaml +115 -0
- package/framework/.claude-plugin/hooks.json +6 -0
- package/framework/.claude-plugin/marketplace.json +32 -0
- package/framework/.claude-plugin/plugin.json +57 -0
- package/framework/.version-bump.json +43 -0
- package/framework/CLAUDE.md +140 -0
- package/framework/CONTRIBUTING.md +219 -0
- package/framework/LICENSE +21 -0
- package/framework/README.en.md +139 -0
- package/framework/README.md +139 -0
- package/framework/RELEASE.md +334 -0
- package/framework/SKILL.md +24 -0
- package/framework/USAGE.md +356 -0
- package/framework/manifest.json +1214 -0
- package/framework/requirements.txt +4 -0
- package/framework/scripts/__init__.py +0 -0
- package/framework/scripts/build_codebase_knowledge.py +76 -0
- package/framework/scripts/bump_version.py +181 -0
- package/framework/scripts/check-dependency-drift.py +69 -0
- package/framework/scripts/check-harness-drift.sh +57 -0
- package/framework/scripts/check-main-merge-hygiene.py +128 -0
- package/framework/scripts/check-skill-dependencies.sh +124 -0
- package/framework/scripts/init-lincoln-branch.sh +300 -0
- package/framework/scripts/init-project.sh +184 -0
- package/framework/scripts/lc-benchmark-cli.py +66 -0
- package/framework/scripts/lincoln-audit.py +288 -0
- package/framework/scripts/lincoln-setup.py +651 -0
- package/framework/scripts/lincoln-status.py +448 -0
- package/framework/scripts/lincoln_benchmark.py +224 -0
- package/framework/scripts/lincoln_benchmark_eval.py +104 -0
- package/framework/scripts/lincoln_benchmark_metrics.py +818 -0
- package/framework/scripts/lincoln_benchmark_report.py +141 -0
- package/framework/scripts/lincoln_command_map.py +289 -0
- package/framework/scripts/lincoln_dependency_manager.py +335 -0
- package/framework/scripts/lincoln_documents.py +175 -0
- package/framework/scripts/lincoln_harness_adapter.py +319 -0
- package/framework/scripts/lincoln_index.py +255 -0
- package/framework/scripts/lincoln_paths.py +198 -0
- package/framework/scripts/lincoln_prd.py +227 -0
- package/framework/scripts/lincoln_role.py +46 -0
- package/framework/scripts/lincoln_scenario.py +59 -0
- package/framework/scripts/lincoln_session_start_metrics.py +71 -0
- package/framework/scripts/lincoln_skill_prompt.py +48 -0
- package/framework/scripts/lincoln_trace.py +335 -0
- package/framework/scripts/lincoln_workflow.py +199 -0
- package/framework/scripts/list-active-lincoln-branches.sh +87 -0
- package/framework/scripts/package-lincoln-plugin.py +340 -0
- package/framework/scripts/run-infrastructure-tests.py +84 -0
- package/framework/scripts/stage_loader.py +1071 -0
- package/framework/scripts/static-check.sh +356 -0
- package/framework/scripts/sync-external-agents.sh +210 -0
- package/framework/scripts/sync-framework-package.mjs +218 -0
- package/framework/scripts/task_tool_guard.py +213 -0
- package/framework/scripts/track-artifacts.py +140 -0
- package/framework/scripts/validate_stage.py +350 -0
- package/{README.md → framework/tools/lincoln/README.md} +4 -4
- package/framework/tools/lincoln/package-lock.json +3349 -0
- package/framework/tools/lincoln/package.json +48 -0
- package/framework/tools/lincoln/src/cli.tsx +60 -0
- package/framework/tools/lincoln/src/components/AudioMeter.tsx +34 -0
- package/framework/tools/lincoln/src/components/CancelledScreen.tsx +11 -0
- package/framework/tools/lincoln/src/components/DevicesMenu.tsx +79 -0
- package/framework/tools/lincoln/src/components/HintBar.tsx +25 -0
- package/framework/tools/lincoln/src/components/LogView.tsx +36 -0
- package/framework/tools/lincoln/src/components/ModelMenu.tsx +122 -0
- package/framework/tools/lincoln/src/components/ReadyScreen.tsx +54 -0
- package/framework/tools/lincoln/src/components/RecordingApp.tsx +211 -0
- package/framework/tools/lincoln/src/components/RecordingScreen.tsx +41 -0
- package/framework/tools/lincoln/src/components/SelectMenu.tsx +53 -0
- package/framework/tools/lincoln/src/components/StatusPanel.tsx +52 -0
- package/framework/tools/lincoln/src/components/StopConfirmation.tsx +32 -0
- package/framework/tools/lincoln/src/config/args.ts +35 -0
- package/framework/tools/lincoln/src/config/loadConfig.ts +81 -0
- package/framework/tools/lincoln/src/config/resolveConfig.ts +85 -0
- package/framework/tools/lincoln/src/devices/listDevices.ts +11 -0
- package/framework/tools/lincoln/src/devices/parseDevices.ts +25 -0
- package/framework/tools/lincoln/src/hooks/useKeyHandler.ts +63 -0
- package/framework/tools/lincoln/src/main.tsx +4 -0
- package/framework/tools/lincoln/src/models/models.ts +34 -0
- package/framework/tools/lincoln/src/models/runWarmup.ts +46 -0
- package/framework/tools/lincoln/src/models/warmupProgress.ts +30 -0
- package/framework/tools/lincoln/src/recording/spawnRecorder.ts +127 -0
- package/framework/tools/lincoln/src/recording/useRecorder.ts +146 -0
- package/framework/tools/lincoln/src/utils/amplitudeToMeter.ts +4 -0
- package/framework/tools/lincoln/src/utils/formatDuration.ts +6 -0
- package/framework/tools/lincoln/src/utils/sessionId.ts +25 -0
- package/framework/tools/lincoln/tests/cli.test.tsx +52 -0
- package/framework/tools/lincoln/tests/components/AudioMeter.test.tsx +31 -0
- package/framework/tools/lincoln/tests/components/CancelledScreen.test.tsx +12 -0
- package/framework/tools/lincoln/tests/components/ReadyScreen.test.tsx +68 -0
- package/framework/tools/lincoln/tests/components/RecordingApp.menus.test.tsx +158 -0
- package/framework/tools/lincoln/tests/components/RecordingApp.test.tsx +248 -0
- package/framework/tools/lincoln/tests/components/RecordingScreen.test.tsx +37 -0
- package/framework/tools/lincoln/tests/components/SelectMenu.test.tsx +59 -0
- package/framework/tools/lincoln/tests/components/StopConfirmation.test.tsx +38 -0
- package/framework/tools/lincoln/tests/config/args.test.ts +49 -0
- package/framework/tools/lincoln/tests/config/loadConfig.test.ts +59 -0
- package/framework/tools/lincoln/tests/config/resolveConfig.test.ts +72 -0
- package/framework/tools/lincoln/tests/devices/parseDevices.test.ts +21 -0
- package/framework/tools/lincoln/tests/hooks/useKeyHandler.enabled.test.tsx +44 -0
- package/framework/tools/lincoln/tests/hooks/useKeyHandler.test.tsx +130 -0
- package/framework/tools/lincoln/tests/models/models.test.ts +27 -0
- package/framework/tools/lincoln/tests/models/warmupProgress.test.ts +25 -0
- package/framework/tools/lincoln/tests/recording/spawnRecorder.test.ts +85 -0
- package/framework/tools/lincoln/tests/recording/useRecorder.test.tsx +172 -0
- package/framework/tools/lincoln/tests/utils/amplitudeToMeter.test.ts +22 -0
- package/framework/tools/lincoln/tests/utils/formatDuration.test.ts +11 -0
- package/framework/tools/lincoln/tests/utils/sessionId.test.ts +30 -0
- package/framework/tools/lincoln/tsconfig.json +22 -0
- package/framework/tools/lincoln/tsconfig.tests.json +10 -0
- package/framework/tools/lincoln/tsup.config.ts +17 -0
- package/framework/tools/lincoln/vitest.config.ts +20 -0
- package/framework/tools/lincoln-installer/package-lock.json +3611 -0
- package/framework/tools/lincoln-installer/package.json +53 -0
- package/framework/tools/lincoln-installer/src/cli.tsx +63 -0
- package/framework/tools/lincoln-installer/src/components/HarnessSelectScreen.tsx +43 -0
- package/framework/tools/lincoln-installer/src/components/InstallerApp.tsx +98 -0
- package/framework/tools/lincoln-installer/src/components/OptionsScreen.tsx +56 -0
- package/framework/tools/lincoln-installer/src/components/ProgressScreen.tsx +25 -0
- package/framework/tools/lincoln-installer/src/components/ResultScreen.tsx +40 -0
- package/framework/tools/lincoln-installer/src/components/SelectMenu.tsx +73 -0
- package/framework/tools/lincoln-installer/src/components/SummaryScreen.tsx +49 -0
- package/framework/tools/lincoln-installer/src/components/UpdateApp.tsx +135 -0
- package/framework/tools/lincoln-installer/src/components/WelcomeScreen.tsx +22 -0
- package/framework/tools/lincoln-installer/src/config/args.ts +76 -0
- package/framework/tools/lincoln-installer/src/config/resolveConfig.ts +33 -0
- package/framework/tools/lincoln-installer/src/config/updateArgs.ts +67 -0
- package/framework/tools/lincoln-installer/src/hooks/useSetup.ts +149 -0
- package/framework/tools/lincoln-installer/src/main.tsx +11 -0
- package/framework/tools/lincoln-installer/src/types.ts +19 -0
- package/framework/tools/lincoln-installer/src/update-main.tsx +11 -0
- package/framework/tools/lincoln-installer/src/update.tsx +90 -0
- package/framework/tools/lincoln-installer/src/utils/detectHarness.ts +51 -0
- package/framework/tools/lincoln-installer/src/utils/runSetup.ts +62 -0
- package/framework/tools/lincoln-installer/src/utils/updateRelease.ts +454 -0
- package/framework/tools/lincoln-installer/tests/components/InstallerApp.test.tsx +88 -0
- package/framework/tools/lincoln-installer/tests/components/SelectMenu.test.tsx +26 -0
- package/framework/tools/lincoln-installer/tests/components/UpdateApp.test.tsx +170 -0
- package/framework/tools/lincoln-installer/tests/components/screens.test.tsx +310 -0
- package/framework/tools/lincoln-installer/tests/config/args.test.ts +66 -0
- package/framework/tools/lincoln-installer/tests/config/resolveConfig.test.ts +75 -0
- package/framework/tools/lincoln-installer/tests/config/updateArgs.test.ts +52 -0
- package/framework/tools/lincoln-installer/tests/hooks/useSetup.test.tsx +213 -0
- package/framework/tools/lincoln-installer/tests/update.test.tsx +108 -0
- package/framework/tools/lincoln-installer/tests/utils/detectHarness.test.ts +40 -0
- package/framework/tools/lincoln-installer/tests/utils/runSetup.test.ts +45 -0
- package/framework/tools/lincoln-installer/tests/utils/updateRelease.test.ts +559 -0
- package/framework/tools/lincoln-installer/tsconfig.json +22 -0
- package/framework/tools/lincoln-installer/tsconfig.tests.json +8 -0
- package/framework/tools/lincoln-installer/tsup.config.ts +17 -0
- package/framework/tools/lincoln-installer/vitest.config.ts +20 -0
- package/framework/tools/lincoln-record/Cargo.lock +1896 -0
- package/framework/tools/lincoln-record/Cargo.toml +24 -0
- package/framework/tools/lincoln-record/diarize/diarize.py +117 -0
- package/framework/tools/lincoln-record/diarize/merge.py +55 -0
- package/framework/tools/lincoln-record/src/audio/capture/microphone.rs +194 -0
- package/framework/tools/lincoln-record/src/audio/capture/mod.rs +1 -0
- package/framework/tools/lincoln-record/src/audio/devices.rs +20 -0
- package/framework/tools/lincoln-record/src/audio/mod.rs +5 -0
- package/framework/tools/lincoln-record/src/audio/resampler.rs +44 -0
- package/framework/tools/lincoln-record/src/audio/saver.rs +87 -0
- package/framework/tools/lincoln-record/src/audio/source.rs +104 -0
- package/framework/tools/lincoln-record/src/cli.rs +96 -0
- package/framework/tools/lincoln-record/src/config.rs +135 -0
- package/framework/tools/lincoln-record/src/lib.rs +6 -0
- package/framework/tools/lincoln-record/src/main.rs +242 -0
- package/framework/tools/lincoln-record/src/model/mod.rs +248 -0
- package/framework/tools/lincoln-record/src/output/metadata.rs +30 -0
- package/framework/tools/lincoln-record/src/output/mod.rs +2 -0
- package/framework/tools/lincoln-record/src/output/transcript.rs +42 -0
- package/framework/tools/lincoln-record/src/transcription/diarization.rs +64 -0
- package/framework/tools/lincoln-record/src/transcription/mod.rs +3 -0
- package/framework/tools/lincoln-record/src/transcription/provider.rs +43 -0
- package/framework/tools/lincoln-record/src/transcription/whisper.rs +176 -0
- package/framework/tools/lincoln-record/tests/cli_args.rs +103 -0
- package/framework/tools/lincoln-record/tests/config_test.rs +70 -0
- package/framework/tools/lincoln-record/tests/devices_test.rs +23 -0
- package/framework/tools/lincoln-record/tests/diarization_tests.rs +101 -0
- package/framework/tools/lincoln-record/tests/integration_tests.rs +44 -0
- package/framework/tools/lincoln-record/tests/model_test.rs +68 -0
- package/framework/tools/lincoln-record/tests/transcription_tests.rs +73 -0
- package/package.json +19 -13
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Lincoln structural validators.
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
python scripts/validate_stage.py --phase entry --check file_exists --args path/to/file
|
|
7
|
+
python scripts/validate_stage.py --phase exit --check artifacts_present
|
|
8
|
+
|
|
9
|
+
Exit code 0 means pass, 1 means fail.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import argparse
|
|
15
|
+
import os
|
|
16
|
+
import re
|
|
17
|
+
import sys
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import Any
|
|
20
|
+
|
|
21
|
+
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
|
22
|
+
if str(PROJECT_ROOT) not in sys.path:
|
|
23
|
+
sys.path.insert(0, str(PROJECT_ROOT))
|
|
24
|
+
|
|
25
|
+
from scripts.lincoln_documents import extract_markdown_version
|
|
26
|
+
from scripts.lincoln_index import VERSION_COMMENT_RE, extract_html_markdown
|
|
27
|
+
from scripts.lincoln_paths import get_process_slug, load_yaml, resolve_state_path
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def fail(message: str) -> None:
|
|
31
|
+
print(f"FAIL: {message}")
|
|
32
|
+
sys.exit(1)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def pass_check(message: str = "") -> None:
|
|
36
|
+
print(f"PASS{' - ' + message if message else ''}")
|
|
37
|
+
sys.exit(0)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def process_slug() -> str:
|
|
41
|
+
env_slug = os.environ.get("LINCOLN_PROCESS_SLUG")
|
|
42
|
+
if env_slug:
|
|
43
|
+
return env_slug
|
|
44
|
+
|
|
45
|
+
state_file = resolve_state_path(None, PROJECT_ROOT)
|
|
46
|
+
if state_file and state_file.exists():
|
|
47
|
+
try:
|
|
48
|
+
state = load_yaml(state_file)
|
|
49
|
+
return get_process_slug(state, state_file)
|
|
50
|
+
except Exception:
|
|
51
|
+
pass
|
|
52
|
+
return "lc-process"
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def process_root() -> Path:
|
|
56
|
+
slug = process_slug()
|
|
57
|
+
root = PROJECT_ROOT / slug
|
|
58
|
+
if root.exists():
|
|
59
|
+
return root
|
|
60
|
+
return PROJECT_ROOT
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def process_path(*parts: str) -> Path:
|
|
64
|
+
return process_root().joinpath(*parts)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def load_state() -> dict[str, Any] | None:
|
|
68
|
+
state_file = resolve_state_path(None, PROJECT_ROOT)
|
|
69
|
+
if not state_file or not state_file.exists():
|
|
70
|
+
return None
|
|
71
|
+
try:
|
|
72
|
+
return load_yaml(state_file)
|
|
73
|
+
except Exception:
|
|
74
|
+
return None
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def get_latest_node_for_stage(state: dict[str, Any], stage_id: str) -> dict[str, Any] | None:
|
|
78
|
+
nodes = state.get("nodes", [])
|
|
79
|
+
matching = [n for n in nodes if n.get("stage_id") == stage_id]
|
|
80
|
+
return matching[-1] if matching else None
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
# ---------------------------------------------------------------------------
|
|
84
|
+
# Checks
|
|
85
|
+
# ---------------------------------------------------------------------------
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def check_file_exists(path: str) -> None:
|
|
89
|
+
target = PROJECT_ROOT / path
|
|
90
|
+
if not target.exists():
|
|
91
|
+
fail(f"File does not exist: {target}")
|
|
92
|
+
pass_check(str(target))
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def check_artifact_exists(path: str) -> None:
|
|
96
|
+
target = process_path(path)
|
|
97
|
+
if not target.exists() or target.stat().st_size == 0:
|
|
98
|
+
fail(f"Artifact missing or empty: {target}")
|
|
99
|
+
pass_check(str(target))
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def check_audio_format_supported(path: str) -> None:
|
|
103
|
+
supported = {".mp3", ".m4a", ".wav", ".mp4", ".mov"}
|
|
104
|
+
ext = Path(path).suffix.lower()
|
|
105
|
+
if ext not in supported:
|
|
106
|
+
fail(f"Unsupported audio format: {ext}. Supported: {', '.join(supported)}")
|
|
107
|
+
pass_check(ext)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def check_artifacts_present() -> None:
|
|
111
|
+
# Deprecated: stage_loader.py now evaluates artifacts_present from stage YAML.
|
|
112
|
+
# Kept for direct CLI usage; without args it cannot determine which artifacts.
|
|
113
|
+
pass_check("artifacts_present delegated to stage_loader")
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def check_previous_stage_completed(prev_stage_id: str) -> None:
|
|
117
|
+
state = load_state()
|
|
118
|
+
if state is None:
|
|
119
|
+
fail("No state file found")
|
|
120
|
+
prev_node = get_latest_node_for_stage(state, prev_stage_id)
|
|
121
|
+
if prev_node and prev_node.get("status") == "completed":
|
|
122
|
+
pass_check(f"previous stage '{prev_stage_id}' completed")
|
|
123
|
+
fail(f"Previous stage '{prev_stage_id}' not completed")
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def check_human_approved() -> None:
|
|
127
|
+
state = load_state()
|
|
128
|
+
if state is None:
|
|
129
|
+
fail("No state file found")
|
|
130
|
+
current_stage = state.get("current_run", {}).get("current_stage")
|
|
131
|
+
if not current_stage:
|
|
132
|
+
fail("No current stage in state")
|
|
133
|
+
latest_node = get_latest_node_for_stage(state, current_stage)
|
|
134
|
+
if latest_node and latest_node.get("gate_passed") and latest_node.get("approved_by"):
|
|
135
|
+
pass_check(f"human approved for stage '{current_stage}'")
|
|
136
|
+
fail(f"Stage '{current_stage}' not approved")
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def _extract_yaml_version(path: Path) -> str | None:
|
|
140
|
+
"""Read a top-level `version` or `contract_version` field from YAML."""
|
|
141
|
+
if not path.exists():
|
|
142
|
+
return None
|
|
143
|
+
try:
|
|
144
|
+
data = load_yaml(path)
|
|
145
|
+
except Exception:
|
|
146
|
+
return None
|
|
147
|
+
if not isinstance(data, dict):
|
|
148
|
+
return None
|
|
149
|
+
return data.get("version") or data.get("contract_version")
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def _extract_document_version(path: Path) -> str | None:
|
|
153
|
+
if path.suffix in (".md", ".markdown"):
|
|
154
|
+
return extract_markdown_version(path)
|
|
155
|
+
if path.suffix in (".yaml", ".yml"):
|
|
156
|
+
return _extract_yaml_version(path)
|
|
157
|
+
if path.suffix == ".html":
|
|
158
|
+
text = path.read_text(encoding="utf-8")
|
|
159
|
+
match = VERSION_COMMENT_RE.search(text)
|
|
160
|
+
return match.group(1) if match else None
|
|
161
|
+
return None
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def check_handoff_contract_valid(path: str) -> None:
|
|
165
|
+
target = PROJECT_ROOT / path
|
|
166
|
+
if not target.exists():
|
|
167
|
+
fail(f"Handoff contract missing: {target}")
|
|
168
|
+
|
|
169
|
+
try:
|
|
170
|
+
data = load_yaml(target)
|
|
171
|
+
except Exception as exc:
|
|
172
|
+
fail(f"Handoff contract is not valid YAML: {target} ({exc})")
|
|
173
|
+
|
|
174
|
+
if not isinstance(data, dict):
|
|
175
|
+
fail(f"Handoff contract must be a YAML mapping: {target}")
|
|
176
|
+
|
|
177
|
+
required_keys = [
|
|
178
|
+
"contract_version",
|
|
179
|
+
"issue_number",
|
|
180
|
+
"feature_slug",
|
|
181
|
+
"from_stage",
|
|
182
|
+
"to_stage",
|
|
183
|
+
"from_agent",
|
|
184
|
+
"to_agent",
|
|
185
|
+
"handoff_type",
|
|
186
|
+
"human_master_doc",
|
|
187
|
+
"based_on",
|
|
188
|
+
"context_pack",
|
|
189
|
+
"reading_rules",
|
|
190
|
+
"open_questions",
|
|
191
|
+
"approval",
|
|
192
|
+
]
|
|
193
|
+
missing = [key for key in required_keys if key not in data]
|
|
194
|
+
if missing:
|
|
195
|
+
fail(f"Handoff contract missing required keys: {', '.join(missing)}")
|
|
196
|
+
|
|
197
|
+
human_doc = data.get("human_master_doc", {})
|
|
198
|
+
if not human_doc.get("path") or not human_doc.get("version"):
|
|
199
|
+
fail("Handoff contract human_master_doc must have path and version")
|
|
200
|
+
|
|
201
|
+
pass_check(f"handoff contract valid: {target}")
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def check_handoff_versions_match(path: str) -> None:
|
|
205
|
+
target = PROJECT_ROOT / path
|
|
206
|
+
if not target.exists():
|
|
207
|
+
fail(f"Handoff contract missing: {target}")
|
|
208
|
+
|
|
209
|
+
try:
|
|
210
|
+
data = load_yaml(target)
|
|
211
|
+
except Exception as exc:
|
|
212
|
+
fail(f"Handoff contract is not valid YAML: {target} ({exc})")
|
|
213
|
+
|
|
214
|
+
if not isinstance(data, dict):
|
|
215
|
+
fail(f"Handoff contract must be a YAML mapping: {target}")
|
|
216
|
+
|
|
217
|
+
based_on = data.get("based_on", [])
|
|
218
|
+
if not isinstance(based_on, list):
|
|
219
|
+
fail("Handoff contract based_on must be a list")
|
|
220
|
+
|
|
221
|
+
mismatches = []
|
|
222
|
+
for item in based_on:
|
|
223
|
+
if not isinstance(item, dict):
|
|
224
|
+
continue
|
|
225
|
+
doc_path = item.get("path", "")
|
|
226
|
+
expected_version = item.get("version", "")
|
|
227
|
+
if not doc_path or not expected_version:
|
|
228
|
+
continue
|
|
229
|
+
full_path = PROJECT_ROOT / doc_path
|
|
230
|
+
actual_version = _extract_document_version(full_path)
|
|
231
|
+
if actual_version is None:
|
|
232
|
+
mismatches.append(f"{doc_path}: could not detect version")
|
|
233
|
+
elif actual_version != expected_version:
|
|
234
|
+
mismatches.append(f"{doc_path}: expected {expected_version}, found {actual_version}")
|
|
235
|
+
|
|
236
|
+
if mismatches:
|
|
237
|
+
fail("Handoff version mismatches:\n - " + "\n - ".join(mismatches))
|
|
238
|
+
|
|
239
|
+
pass_check("handoff versions match")
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def check_portal_index_exists() -> None:
|
|
243
|
+
target = process_root() / "index.html"
|
|
244
|
+
if not target.exists():
|
|
245
|
+
fail(f"Portal index missing: {target}")
|
|
246
|
+
pass_check(f"portal index exists: {target}")
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
# ---------------------------------------------------------------------------
|
|
250
|
+
# PRD checks
|
|
251
|
+
# ---------------------------------------------------------------------------
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
REQUIRED_PRD_SECTIONS = [
|
|
255
|
+
"## 1. 需求背景",
|
|
256
|
+
"## 2. 用户故事",
|
|
257
|
+
"## 3. 功能拆解",
|
|
258
|
+
"## 4. 业务流程图",
|
|
259
|
+
"## 5. 验收标准",
|
|
260
|
+
"## 6. 业务规则",
|
|
261
|
+
"## 7. 非功能需求",
|
|
262
|
+
"## 8. 关联系统/接口",
|
|
263
|
+
"## 9. 相关产物链接",
|
|
264
|
+
"## 10. 风险与开放问题",
|
|
265
|
+
]
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def check_prd_has_required_sections(path: str) -> None:
|
|
269
|
+
target = PROJECT_ROOT / path
|
|
270
|
+
if not target.exists():
|
|
271
|
+
fail(f"PRD missing: {target}")
|
|
272
|
+
|
|
273
|
+
if target.suffix == ".html":
|
|
274
|
+
text = extract_html_markdown(target)
|
|
275
|
+
else:
|
|
276
|
+
text = target.read_text(encoding="utf-8")
|
|
277
|
+
|
|
278
|
+
missing = [section for section in REQUIRED_PRD_SECTIONS if section not in text]
|
|
279
|
+
if missing:
|
|
280
|
+
fail(f"PRD missing required sections: {', '.join(missing)}")
|
|
281
|
+
|
|
282
|
+
pass_check("PRD has all required sections")
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def check_prd_snapshot_present(path: str) -> None:
|
|
286
|
+
target = PROJECT_ROOT / path
|
|
287
|
+
if not target.exists():
|
|
288
|
+
fail(f"PRD missing: {target}")
|
|
289
|
+
|
|
290
|
+
version = extract_markdown_version(target) if target.suffix != ".html" else _extract_document_version(target)
|
|
291
|
+
if not version:
|
|
292
|
+
fail(f"PRD missing version marker: {target}")
|
|
293
|
+
|
|
294
|
+
if target.suffix == ".html":
|
|
295
|
+
snapshot_path = target.parent / "snapshots" / f"prd-{version}.html"
|
|
296
|
+
else:
|
|
297
|
+
snapshot_path = target.with_name(f"prd-{version}.md")
|
|
298
|
+
if not snapshot_path.exists():
|
|
299
|
+
fail(f"PRD snapshot missing: {snapshot_path}. Run 'python scripts/lincoln_prd.py freeze' after approval.")
|
|
300
|
+
|
|
301
|
+
pass_check(f"PRD snapshot present: {snapshot_path}")
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
# ---------------------------------------------------------------------------
|
|
305
|
+
# Registry
|
|
306
|
+
# ---------------------------------------------------------------------------
|
|
307
|
+
|
|
308
|
+
ENTRY_CHECKS = {
|
|
309
|
+
"file_exists": check_file_exists,
|
|
310
|
+
"artifact_exists": check_artifact_exists,
|
|
311
|
+
"audio_format_supported": check_audio_format_supported,
|
|
312
|
+
"previous_stage_completed": check_previous_stage_completed,
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
EXIT_CHECKS = {
|
|
316
|
+
"file_exists": check_file_exists,
|
|
317
|
+
"artifact_exists": check_artifact_exists,
|
|
318
|
+
"artifacts_present": check_artifacts_present,
|
|
319
|
+
"human_approved": check_human_approved,
|
|
320
|
+
"handoff_contract_valid": check_handoff_contract_valid,
|
|
321
|
+
"handoff_versions_match": check_handoff_versions_match,
|
|
322
|
+
"prd_has_required_sections": check_prd_has_required_sections,
|
|
323
|
+
"prd_snapshot_present": check_prd_snapshot_present,
|
|
324
|
+
"portal_index_exists": check_portal_index_exists,
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
def main() -> int:
|
|
329
|
+
parser = argparse.ArgumentParser(description="Lincoln structural validators")
|
|
330
|
+
parser.add_argument("--phase", required=True, choices=["entry", "exit"])
|
|
331
|
+
parser.add_argument("--check", required=True)
|
|
332
|
+
parser.add_argument("--args", default="", help="Comma-separated arguments for the check")
|
|
333
|
+
parser.add_argument("--state-file", type=Path, default=None, help="Path to workflow state file")
|
|
334
|
+
args = parser.parse_args()
|
|
335
|
+
|
|
336
|
+
registry = ENTRY_CHECKS if args.phase == "entry" else EXIT_CHECKS
|
|
337
|
+
check_fn = registry.get(args.check)
|
|
338
|
+
if not check_fn:
|
|
339
|
+
fail(f"Unknown check: {args.check}. Available: {', '.join(registry.keys())}")
|
|
340
|
+
|
|
341
|
+
check_args = [a.strip() for a in args.args.split(",")] if args.args else []
|
|
342
|
+
try:
|
|
343
|
+
check_fn(*check_args)
|
|
344
|
+
except TypeError as e:
|
|
345
|
+
fail(f"Invalid arguments for check '{args.check}': {e}")
|
|
346
|
+
return 0
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
if __name__ == "__main__":
|
|
350
|
+
sys.exit(main())
|
|
@@ -22,7 +22,7 @@ npm link
|
|
|
22
22
|
安装后,全局可用:
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
|
-
lincoln --help
|
|
25
|
+
lincoln-record --help
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
## 使用
|
|
@@ -30,7 +30,7 @@ lincoln --help
|
|
|
30
30
|
### 基本用法
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
|
-
lincoln 2026-06-28-checkout-interview \
|
|
33
|
+
lincoln-record 2026-06-28-checkout-interview \
|
|
34
34
|
--topic "结算流程 redesign 需求访谈" \
|
|
35
35
|
--design-id checkout-redesign \
|
|
36
36
|
--branch lincoln/2026-06-28-recording-checkout-redesign
|
|
@@ -48,7 +48,7 @@ audio-meter-style: wave
|
|
|
48
48
|
EOF
|
|
49
49
|
|
|
50
50
|
# 直接运行
|
|
51
|
-
lincoln 2026-06-28-checkout-interview
|
|
51
|
+
lincoln-record 2026-06-28-checkout-interview
|
|
52
52
|
```
|
|
53
53
|
|
|
54
54
|
### 用户级配置
|
|
@@ -111,7 +111,7 @@ claude process-interview 2026-06-28-checkout-interview
|
|
|
111
111
|
## CLI 选项
|
|
112
112
|
|
|
113
113
|
```
|
|
114
|
-
lincoln [session-id] [options]
|
|
114
|
+
lincoln-record [session-id] [options]
|
|
115
115
|
|
|
116
116
|
Options:
|
|
117
117
|
--topic 访谈主题
|