@sushanglewis/lincoln 1.5.0 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.d.ts +3 -0
- package/dist/main.js +1286 -916
- 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,340 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Deterministic packaging for the Lincoln plugin (#68).
|
|
3
|
+
|
|
4
|
+
Builds a reproducible distribution archive from an explicit allowlist, rejects
|
|
5
|
+
dirty worktrees, regenerates harness artifacts after version bumps, and emits a
|
|
6
|
+
SHA256 checksum. Does not upload to any marketplace or registry.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import argparse
|
|
12
|
+
import hashlib
|
|
13
|
+
import json
|
|
14
|
+
import os
|
|
15
|
+
import shutil
|
|
16
|
+
import subprocess
|
|
17
|
+
import sys
|
|
18
|
+
import tarfile
|
|
19
|
+
import zipfile
|
|
20
|
+
from datetime import datetime, timezone
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
from typing import Iterable
|
|
23
|
+
|
|
24
|
+
ROOT = Path(__file__).resolve().parents[1]
|
|
25
|
+
|
|
26
|
+
ALLOWLIST_DIRS = (".claude", ".claude-plugin", "scripts", "tools")
|
|
27
|
+
ALLOWLIST_FILES = (
|
|
28
|
+
"README.md",
|
|
29
|
+
"README.en.md",
|
|
30
|
+
"USAGE.md",
|
|
31
|
+
"CONTRIBUTING.md",
|
|
32
|
+
"CLAUDE.md",
|
|
33
|
+
"LICENSE",
|
|
34
|
+
"RELEASE.md",
|
|
35
|
+
".version-bump.json",
|
|
36
|
+
"requirements.txt",
|
|
37
|
+
"SKILL.md",
|
|
38
|
+
)
|
|
39
|
+
DENYLIST_NAMES = {
|
|
40
|
+
".git",
|
|
41
|
+
".context",
|
|
42
|
+
".venv",
|
|
43
|
+
"venv",
|
|
44
|
+
"dist",
|
|
45
|
+
"oss",
|
|
46
|
+
".pytest_cache",
|
|
47
|
+
"__pycache__",
|
|
48
|
+
".DS_Store",
|
|
49
|
+
"node_modules",
|
|
50
|
+
}
|
|
51
|
+
DENYLIST_PREFIXES = ("issue-",)
|
|
52
|
+
SKIP_PATHS = (
|
|
53
|
+
".claude/templates/issue-package",
|
|
54
|
+
"tools/lincoln-installer/dist",
|
|
55
|
+
"tools/lincoln-installer/node_modules",
|
|
56
|
+
"tools/lincoln-installer/coverage",
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
|
|
61
|
+
parser = argparse.ArgumentParser(
|
|
62
|
+
description="Build or validate a deterministic Lincoln plugin package."
|
|
63
|
+
)
|
|
64
|
+
parser.add_argument(
|
|
65
|
+
"--root",
|
|
66
|
+
type=Path,
|
|
67
|
+
default=ROOT,
|
|
68
|
+
help="Repository root (default: repository containing this script).",
|
|
69
|
+
)
|
|
70
|
+
subparsers = parser.add_subparsers(dest="command", required=True)
|
|
71
|
+
|
|
72
|
+
pkg = subparsers.add_parser("package", help="Build the distribution archive.")
|
|
73
|
+
pkg.add_argument(
|
|
74
|
+
"--output-dir",
|
|
75
|
+
type=Path,
|
|
76
|
+
default=Path("dist"),
|
|
77
|
+
help="Output directory for the archive and checksum.",
|
|
78
|
+
)
|
|
79
|
+
pkg.add_argument(
|
|
80
|
+
"--format",
|
|
81
|
+
choices=("tgz", "zip"),
|
|
82
|
+
default="tgz",
|
|
83
|
+
help="Archive format (default: tgz).",
|
|
84
|
+
)
|
|
85
|
+
pkg.add_argument(
|
|
86
|
+
"--force-harness",
|
|
87
|
+
action="store_true",
|
|
88
|
+
help="Regenerate harness artifacts even if they already exist.",
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
chk = subparsers.add_parser(
|
|
92
|
+
"check", help="Validate allowlist/denylist without building."
|
|
93
|
+
)
|
|
94
|
+
chk.add_argument(
|
|
95
|
+
"--check-dirty",
|
|
96
|
+
action="store_true",
|
|
97
|
+
help="Also reject dirty worktrees in check mode.",
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
return parser.parse_args(argv)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def load_version(root: Path) -> str:
|
|
104
|
+
source = root / ".version-bump.json"
|
|
105
|
+
if not source.exists():
|
|
106
|
+
sys.exit("missing version source: .version-bump.json")
|
|
107
|
+
data = json.loads(source.read_text(encoding="utf-8"))
|
|
108
|
+
version = data.get("version", "")
|
|
109
|
+
if not (isinstance(version, str) and len(version.split(".")) == 3):
|
|
110
|
+
sys.exit(f".version-bump.json has invalid version: {version!r}")
|
|
111
|
+
return version
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def is_dirty(root: Path) -> bool:
|
|
115
|
+
"""Return True if the working tree has uncommitted tracked changes."""
|
|
116
|
+
for diff_flag in ("--quiet", "--cached", "--quiet"):
|
|
117
|
+
result = subprocess.run(
|
|
118
|
+
["git", "diff", diff_flag, "HEAD"],
|
|
119
|
+
cwd=root,
|
|
120
|
+
capture_output=True,
|
|
121
|
+
)
|
|
122
|
+
if result.returncode != 0:
|
|
123
|
+
return True
|
|
124
|
+
return False
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def git_head_timestamp(root: Path) -> int:
|
|
128
|
+
"""Return the Unix timestamp of HEAD for reproducible archives."""
|
|
129
|
+
result = subprocess.run(
|
|
130
|
+
["git", "log", "-1", "--format=%ct"],
|
|
131
|
+
cwd=root,
|
|
132
|
+
capture_output=True,
|
|
133
|
+
text=True,
|
|
134
|
+
)
|
|
135
|
+
if result.returncode != 0 or not result.stdout.strip():
|
|
136
|
+
env_epoch = os.environ.get("SOURCE_DATE_EPOCH", "")
|
|
137
|
+
if env_epoch.isdigit():
|
|
138
|
+
return int(env_epoch)
|
|
139
|
+
return 0
|
|
140
|
+
return int(result.stdout.strip())
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def regenerate_harness(root: Path, force: bool) -> None:
|
|
144
|
+
"""Regenerate codex/opencode harness artifacts if they exist or force=True."""
|
|
145
|
+
adapter = root / "scripts" / "lincoln_harness_adapter.py"
|
|
146
|
+
any_artifact = any(
|
|
147
|
+
(root / ".claude" / "harnesses" / f"{harness}.yaml").exists()
|
|
148
|
+
for harness in ("codex", "opencode")
|
|
149
|
+
)
|
|
150
|
+
if not adapter.exists():
|
|
151
|
+
if any_artifact:
|
|
152
|
+
sys.exit("missing harness adapter: scripts/lincoln_harness_adapter.py")
|
|
153
|
+
return
|
|
154
|
+
|
|
155
|
+
for harness in ("codex", "opencode"):
|
|
156
|
+
artifact = root / ".claude" / "harnesses" / f"{harness}.yaml"
|
|
157
|
+
if artifact.exists() and not force:
|
|
158
|
+
continue
|
|
159
|
+
print(f"Regenerating harness artifact: {artifact.relative_to(root)}")
|
|
160
|
+
result = subprocess.run(
|
|
161
|
+
[sys.executable, str(adapter), "--harness", harness],
|
|
162
|
+
cwd=root,
|
|
163
|
+
capture_output=True,
|
|
164
|
+
text=True,
|
|
165
|
+
)
|
|
166
|
+
if result.returncode != 0:
|
|
167
|
+
print(result.stderr, file=sys.stderr)
|
|
168
|
+
sys.exit(f"harness generation failed for {harness}")
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def collect_sources(root: Path) -> Iterable[Path]:
|
|
172
|
+
"""Yield every file that belongs in the package, validating the allowlist."""
|
|
173
|
+
for name in ALLOWLIST_DIRS:
|
|
174
|
+
src_dir = root / name
|
|
175
|
+
if not src_dir.exists():
|
|
176
|
+
sys.exit(f"allowlist directory missing: {name}")
|
|
177
|
+
for path in src_dir.rglob("*"):
|
|
178
|
+
if path.is_file():
|
|
179
|
+
yield path
|
|
180
|
+
|
|
181
|
+
for name in ALLOWLIST_FILES:
|
|
182
|
+
src_file = root / name
|
|
183
|
+
if not src_file.exists():
|
|
184
|
+
sys.exit(f"allowlist file missing: {name}")
|
|
185
|
+
yield src_file
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def is_denylisted(relative: str) -> bool:
|
|
189
|
+
parts = Path(relative).parts
|
|
190
|
+
return any(
|
|
191
|
+
part in DENYLIST_NAMES or part.startswith(DENYLIST_PREFIXES)
|
|
192
|
+
for part in parts
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def is_skipped(relative: str) -> bool:
|
|
197
|
+
return any(relative.startswith(skip) for skip in SKIP_PATHS)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def clean_generated(root: Path) -> None:
|
|
201
|
+
"""Remove generated artifacts that should never be packaged."""
|
|
202
|
+
for name in ALLOWLIST_DIRS:
|
|
203
|
+
base = root / name
|
|
204
|
+
if not base.exists():
|
|
205
|
+
continue
|
|
206
|
+
for pycache in base.rglob("__pycache__"):
|
|
207
|
+
if pycache.is_dir():
|
|
208
|
+
shutil.rmtree(pycache, ignore_errors=True)
|
|
209
|
+
for ds_store in base.rglob(".DS_Store"):
|
|
210
|
+
if ds_store.is_file():
|
|
211
|
+
ds_store.unlink(missing_ok=True)
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def validate_manifest(root: Path) -> None:
|
|
215
|
+
clean_generated(root)
|
|
216
|
+
version = load_version(root)
|
|
217
|
+
for src in collect_sources(root):
|
|
218
|
+
rel = str(src.relative_to(root))
|
|
219
|
+
if is_skipped(rel):
|
|
220
|
+
continue
|
|
221
|
+
if is_denylisted(rel):
|
|
222
|
+
sys.exit(f"denylist violation in package: {rel}")
|
|
223
|
+
print(f"Package manifest OK for version {version}")
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def stage_package(root: Path, staging: Path) -> None:
|
|
227
|
+
"""Copy allowlisted sources into a staging directory for archiving."""
|
|
228
|
+
clean_generated(root)
|
|
229
|
+
for src in collect_sources(root):
|
|
230
|
+
rel = src.relative_to(root)
|
|
231
|
+
if is_skipped(str(rel)) or is_denylisted(str(rel)):
|
|
232
|
+
continue
|
|
233
|
+
dst = staging / rel
|
|
234
|
+
dst.parent.mkdir(parents=True, exist_ok=True)
|
|
235
|
+
shutil.copy2(src, dst)
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def archive_mtime(root: Path) -> int:
|
|
239
|
+
env = os.environ.get("SOURCE_DATE_EPOCH", "")
|
|
240
|
+
if env.isdigit():
|
|
241
|
+
return int(env)
|
|
242
|
+
return git_head_timestamp(root)
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def archive_time_tuple(epoch: int) -> tuple[int, int, int, int, int, int]:
|
|
246
|
+
dt = datetime.fromtimestamp(epoch, tz=timezone.utc)
|
|
247
|
+
return (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second)
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def build_tgz(root: Path, staging: Path, output: Path, epoch: int) -> None:
|
|
251
|
+
with tarfile.open(output, "w:gz") as tar:
|
|
252
|
+
|
|
253
|
+
def _reset(tarinfo: tarfile.TarInfo) -> tarfile.TarInfo:
|
|
254
|
+
tarinfo.mtime = epoch
|
|
255
|
+
tarinfo.uid = tarinfo.gid = 0
|
|
256
|
+
tarinfo.uname = tarinfo.gname = ""
|
|
257
|
+
return tarinfo
|
|
258
|
+
|
|
259
|
+
tar.add(staging, arcname=f"lincoln-{load_version(root)}", filter=_reset)
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def build_zip(root: Path, staging: Path, output: Path, epoch: int) -> None:
|
|
263
|
+
time_tuple = archive_time_tuple(epoch)
|
|
264
|
+
with zipfile.ZipFile(output, "w", zipfile.ZIP_DEFLATED) as zf:
|
|
265
|
+
for file_path in staging.rglob("*"):
|
|
266
|
+
if not file_path.is_file():
|
|
267
|
+
continue
|
|
268
|
+
arcname = (
|
|
269
|
+
f"lincoln-{load_version(root)}/{file_path.relative_to(staging)}"
|
|
270
|
+
)
|
|
271
|
+
zf.write(file_path, arcname)
|
|
272
|
+
# Normalize timestamps after writing (zipfile does not expose this easily)
|
|
273
|
+
info = zf.getinfo(arcname)
|
|
274
|
+
info.date_time = time_tuple
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def write_checksum(output: Path) -> None:
|
|
278
|
+
sha256 = hashlib.sha256(output.read_bytes()).hexdigest()
|
|
279
|
+
checksum_file = output.with_suffix(output.suffix + ".sha256")
|
|
280
|
+
checksum_file.write_text(f"{sha256} {output.name}\n", encoding="utf-8")
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
def cmd_check(args: argparse.Namespace) -> int:
|
|
284
|
+
if args.check_dirty and is_dirty(args.root):
|
|
285
|
+
print("error: working tree has uncommitted changes", file=sys.stderr)
|
|
286
|
+
return 1
|
|
287
|
+
validate_manifest(args.root)
|
|
288
|
+
return 0
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
def cmd_package(args: argparse.Namespace) -> int:
|
|
292
|
+
if is_dirty(args.root):
|
|
293
|
+
print(
|
|
294
|
+
"error: refusing to package a dirty working tree. "
|
|
295
|
+
"Commit or stash changes first.",
|
|
296
|
+
file=sys.stderr,
|
|
297
|
+
)
|
|
298
|
+
return 1
|
|
299
|
+
|
|
300
|
+
regenerate_harness(args.root, args.force_harness)
|
|
301
|
+
validate_manifest(args.root)
|
|
302
|
+
|
|
303
|
+
output_dir = args.root / args.output_dir
|
|
304
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
305
|
+
version = load_version(args.root)
|
|
306
|
+
ext = "tar.gz" if args.format == "tgz" else "zip"
|
|
307
|
+
output = output_dir / f"lincoln-{version}.{ext}"
|
|
308
|
+
|
|
309
|
+
epoch = archive_mtime(args.root)
|
|
310
|
+
|
|
311
|
+
staging = args.root / ".context" / "package-staging"
|
|
312
|
+
if staging.exists():
|
|
313
|
+
shutil.rmtree(staging)
|
|
314
|
+
staging.mkdir(parents=True)
|
|
315
|
+
|
|
316
|
+
try:
|
|
317
|
+
stage_package(args.root, staging)
|
|
318
|
+
if args.format == "tgz":
|
|
319
|
+
build_tgz(args.root, staging, output, epoch)
|
|
320
|
+
else:
|
|
321
|
+
build_zip(args.root, staging, output, epoch)
|
|
322
|
+
write_checksum(output)
|
|
323
|
+
print(f"Packaged {output.relative_to(args.root)}")
|
|
324
|
+
print(f"Checksum {output.with_suffix(output.suffix + '.sha256').relative_to(args.root)}")
|
|
325
|
+
return 0
|
|
326
|
+
finally:
|
|
327
|
+
shutil.rmtree(staging, ignore_errors=True)
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
def main(argv: list[str] | None = None) -> int:
|
|
331
|
+
args = parse_args(argv)
|
|
332
|
+
if args.command == "check":
|
|
333
|
+
return cmd_check(args)
|
|
334
|
+
if args.command == "package":
|
|
335
|
+
return cmd_package(args)
|
|
336
|
+
return 2
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
if __name__ == "__main__":
|
|
340
|
+
sys.exit(main())
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Run the deterministic infrastructure test suite (#67).
|
|
3
|
+
|
|
4
|
+
This script is the entry point for the CI `infrastructure-tests` job. It runs
|
|
5
|
+
only tests that do not depend on LLM calls, network access, or stochastic
|
|
6
|
+
behavior, so they can be used as a fast, reliable gate.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import argparse
|
|
12
|
+
import subprocess
|
|
13
|
+
import sys
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
ROOT = Path(__file__).resolve().parents[1]
|
|
17
|
+
|
|
18
|
+
INFRASTRUCTURE_TESTS = [
|
|
19
|
+
"tests/test_yaml_schemas.py",
|
|
20
|
+
"tests/test_bump_version.py",
|
|
21
|
+
"tests/test_harness_default_off.py",
|
|
22
|
+
"tests/test_agent_contract.py",
|
|
23
|
+
"tests/test_session_start_shape.py",
|
|
24
|
+
"tests/test_hook_session_start.py",
|
|
25
|
+
"tests/test_infrastructure_layers.py",
|
|
26
|
+
"tests/test_benchmark_opt_in.py",
|
|
27
|
+
"tests/test_new_skills.py",
|
|
28
|
+
"tests/test_package_lincoln_plugin.py",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def parse_args() -> argparse.Namespace:
|
|
33
|
+
parser = argparse.ArgumentParser(
|
|
34
|
+
description="Run Lincoln deterministic infrastructure tests."
|
|
35
|
+
)
|
|
36
|
+
parser.add_argument(
|
|
37
|
+
"--ci",
|
|
38
|
+
action="store_true",
|
|
39
|
+
help="Exit with non-zero status if any test fails.",
|
|
40
|
+
)
|
|
41
|
+
parser.add_argument(
|
|
42
|
+
"--collect-only",
|
|
43
|
+
action="store_true",
|
|
44
|
+
help="List the tests that would be run without executing them.",
|
|
45
|
+
)
|
|
46
|
+
parser.add_argument(
|
|
47
|
+
"pytest_args",
|
|
48
|
+
nargs="*",
|
|
49
|
+
help="Additional arguments to pass to pytest.",
|
|
50
|
+
)
|
|
51
|
+
return parser.parse_args()
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def main() -> int:
|
|
55
|
+
args = parse_args()
|
|
56
|
+
|
|
57
|
+
missing = [t for t in INFRASTRUCTURE_TESTS if not (ROOT / t).exists()]
|
|
58
|
+
if missing:
|
|
59
|
+
print("Missing infrastructure test files:")
|
|
60
|
+
for m in missing:
|
|
61
|
+
print(f" - {m}")
|
|
62
|
+
return 1
|
|
63
|
+
|
|
64
|
+
if args.collect_only:
|
|
65
|
+
print("Infrastructure test suite:")
|
|
66
|
+
for t in INFRASTRUCTURE_TESTS:
|
|
67
|
+
print(f" {t}")
|
|
68
|
+
return 0
|
|
69
|
+
|
|
70
|
+
cmd = [
|
|
71
|
+
sys.executable,
|
|
72
|
+
"-m",
|
|
73
|
+
"pytest",
|
|
74
|
+
*INFRASTRUCTURE_TESTS,
|
|
75
|
+
"-v",
|
|
76
|
+
*(args.pytest_args or []),
|
|
77
|
+
]
|
|
78
|
+
print(f"Running: {' '.join(cmd)}")
|
|
79
|
+
result = subprocess.run(cmd, cwd=ROOT)
|
|
80
|
+
return result.returncode
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
if __name__ == "__main__":
|
|
84
|
+
sys.exit(main())
|