@litfamily/litopencode 1.0.0
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/.gitattributes +8 -0
- package/ATTRIBUTION.md +56 -0
- package/CHANGELOG.md +267 -0
- package/CODE_OF_CONDUCT.md +30 -0
- package/CONTRIBUTING.md +82 -0
- package/LICENSE +21 -0
- package/README-Ko-KR.md +252 -0
- package/README.md +252 -0
- package/SECURITY.md +36 -0
- package/SUPPORT.md +37 -0
- package/bin/litopencode +3 -0
- package/bin/litopencode.cjs +10 -0
- package/dist/activation-managed-prompts.d.ts +2 -0
- package/dist/activation-managed-prompts.js +51 -0
- package/dist/activation-primary-prompts.d.ts +2 -0
- package/dist/activation-primary-prompts.js +176 -0
- package/dist/activation-probe.d.ts +3 -0
- package/dist/activation-probe.js +19 -0
- package/dist/activation-prompt-utils.d.ts +6 -0
- package/dist/activation-prompt-utils.js +36 -0
- package/dist/activation-routing.d.ts +5 -0
- package/dist/activation-routing.js +340 -0
- package/dist/activation-workflow-prompts.d.ts +26 -0
- package/dist/activation-workflow-prompts.js +295 -0
- package/dist/activation.d.ts +24 -0
- package/dist/activation.js +152 -0
- package/dist/agents/defaults.d.ts +15 -0
- package/dist/agents/defaults.js +112 -0
- package/dist/agents/registry.d.ts +65 -0
- package/dist/agents/registry.js +319 -0
- package/dist/agents/specialists.d.ts +49 -0
- package/dist/agents/specialists.js +307 -0
- package/dist/agents/types.d.ts +55 -0
- package/dist/agents/types.js +4 -0
- package/dist/agents.d.ts +4 -0
- package/dist/agents.js +3 -0
- package/dist/benchmark.d.ts +94 -0
- package/dist/benchmark.js +172 -0
- package/dist/bounded-authority-hooks.d.ts +19 -0
- package/dist/bounded-authority-hooks.js +157 -0
- package/dist/bounded-authority.d.ts +184 -0
- package/dist/bounded-authority.js +825 -0
- package/dist/cache-metrics.d.ts +54 -0
- package/dist/cache-metrics.js +81 -0
- package/dist/cli/args.d.ts +5 -0
- package/dist/cli/args.js +415 -0
- package/dist/cli/auto-update.d.ts +117 -0
- package/dist/cli/auto-update.js +604 -0
- package/dist/cli/command-alias-ownership.d.ts +2 -0
- package/dist/cli/command-alias-ownership.js +14 -0
- package/dist/cli/command-aliases.d.ts +12 -0
- package/dist/cli/command-aliases.js +112 -0
- package/dist/cli/doctor.d.ts +2 -0
- package/dist/cli/doctor.js +175 -0
- package/dist/cli/host-capabilities.d.ts +12 -0
- package/dist/cli/host-capabilities.js +25 -0
- package/dist/cli/host-limits.d.ts +21 -0
- package/dist/cli/host-limits.js +83 -0
- package/dist/cli/install-config.d.ts +13 -0
- package/dist/cli/install-config.js +201 -0
- package/dist/cli/install-report.d.ts +2 -0
- package/dist/cli/install-report.js +180 -0
- package/dist/cli/install-tui.d.ts +12 -0
- package/dist/cli/install-tui.js +174 -0
- package/dist/cli/install.d.ts +2 -0
- package/dist/cli/install.js +264 -0
- package/dist/cli/json.d.ts +4 -0
- package/dist/cli/json.js +31 -0
- package/dist/cli/loop.d.ts +3 -0
- package/dist/cli/loop.js +135 -0
- package/dist/cli/lsp-capability.d.ts +17 -0
- package/dist/cli/lsp-capability.js +92 -0
- package/dist/cli/managed-skill-assets.d.ts +23 -0
- package/dist/cli/managed-skill-assets.js +117 -0
- package/dist/cli/model-catalog.d.ts +21 -0
- package/dist/cli/model-catalog.js +107 -0
- package/dist/cli/model-policy.d.ts +3 -0
- package/dist/cli/model-policy.js +143 -0
- package/dist/cli/model-routing.d.ts +5 -0
- package/dist/cli/model-routing.js +208 -0
- package/dist/cli/native-canonical-backup.d.ts +9 -0
- package/dist/cli/native-canonical-backup.js +96 -0
- package/dist/cli/native-canonical-cache.d.ts +9 -0
- package/dist/cli/native-canonical-cache.js +37 -0
- package/dist/cli/native-skill-install.d.ts +2 -0
- package/dist/cli/native-skill-install.js +128 -0
- package/dist/cli/native-skill-integrity.d.ts +25 -0
- package/dist/cli/native-skill-integrity.js +178 -0
- package/dist/cli/native-skill-tree.d.ts +12 -0
- package/dist/cli/native-skill-tree.js +104 -0
- package/dist/cli/native-skills.d.ts +22 -0
- package/dist/cli/native-skills.js +105 -0
- package/dist/cli/plugin-mutation.d.ts +4 -0
- package/dist/cli/plugin-mutation.js +89 -0
- package/dist/cli/scientific-visualization-dependencies.d.ts +18 -0
- package/dist/cli/scientific-visualization-dependencies.js +91 -0
- package/dist/cli/skill-loop.d.ts +3 -0
- package/dist/cli/skill-loop.js +649 -0
- package/dist/cli/types.d.ts +188 -0
- package/dist/cli/types.js +1 -0
- package/dist/cli/update-check.d.ts +2 -0
- package/dist/cli/update-check.js +15 -0
- package/dist/cli/update-notifier.d.ts +70 -0
- package/dist/cli/update-notifier.js +717 -0
- package/dist/cli/vendor-path-migration.d.ts +9 -0
- package/dist/cli/vendor-path-migration.js +96 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.js +250 -0
- package/dist/commands.d.ts +331 -0
- package/dist/commands.js +600 -0
- package/dist/config-parser.d.ts +5 -0
- package/dist/config-parser.js +274 -0
- package/dist/config.d.ts +72 -0
- package/dist/config.js +157 -0
- package/dist/deliverable-hedge-guard.d.ts +26 -0
- package/dist/deliverable-hedge-guard.js +302 -0
- package/dist/durable-plan.d.ts +23 -0
- package/dist/durable-plan.js +349 -0
- package/dist/features.d.ts +828 -0
- package/dist/features.js +1109 -0
- package/dist/hooks.d.ts +17 -0
- package/dist/hooks.js +83 -0
- package/dist/ignition.d.ts +14 -0
- package/dist/ignition.js +33 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.js +30 -0
- package/dist/inert-data.d.ts +2 -0
- package/dist/inert-data.js +13 -0
- package/dist/knowledge.d.ts +98 -0
- package/dist/knowledge.js +961 -0
- package/dist/ledger.d.ts +181 -0
- package/dist/ledger.js +1179 -0
- package/dist/lit-fetch-classify.d.ts +8 -0
- package/dist/lit-fetch-classify.js +107 -0
- package/dist/lit-fetch-content.d.ts +2 -0
- package/dist/lit-fetch-content.js +43 -0
- package/dist/lit-fetch-http.d.ts +10 -0
- package/dist/lit-fetch-http.js +82 -0
- package/dist/lit-fetch-result.d.ts +2 -0
- package/dist/lit-fetch-result.js +65 -0
- package/dist/lit-fetch-ssrf.d.ts +9 -0
- package/dist/lit-fetch-ssrf.js +77 -0
- package/dist/lit-fetch-url.d.ts +3 -0
- package/dist/lit-fetch-url.js +28 -0
- package/dist/lit-fetch.d.ts +69 -0
- package/dist/lit-fetch.js +84 -0
- package/dist/lit-mark.d.ts +17 -0
- package/dist/lit-mark.js +129 -0
- package/dist/logger.d.ts +9 -0
- package/dist/logger.js +21 -0
- package/dist/model-route-policy.d.ts +25 -0
- package/dist/model-route-policy.js +129 -0
- package/dist/reader-facing-output.d.ts +3 -0
- package/dist/reader-facing-output.js +28 -0
- package/dist/rules/discovery.d.ts +36 -0
- package/dist/rules/discovery.js +270 -0
- package/dist/rules/engine.d.ts +43 -0
- package/dist/rules/engine.js +236 -0
- package/dist/rules/frontmatter.d.ts +16 -0
- package/dist/rules/frontmatter.js +179 -0
- package/dist/rules/glob.d.ts +12 -0
- package/dist/rules/glob.js +233 -0
- package/dist/rules/hooks.d.ts +25 -0
- package/dist/rules/hooks.js +75 -0
- package/dist/rules/output-style.d.ts +1 -0
- package/dist/rules/output-style.js +20 -0
- package/dist/scientific-visualization-banner.d.ts +1 -0
- package/dist/scientific-visualization-banner.js +2 -0
- package/dist/search-workflow-ideas.d.ts +67 -0
- package/dist/search-workflow-ideas.js +128 -0
- package/dist/secret-shapes.d.ts +9 -0
- package/dist/secret-shapes.js +63 -0
- package/dist/server.d.ts +6 -0
- package/dist/server.js +129 -0
- package/dist/session-lineage.d.ts +8 -0
- package/dist/session-lineage.js +12 -0
- package/dist/skill-loop/apply.d.ts +19 -0
- package/dist/skill-loop/apply.js +483 -0
- package/dist/skill-loop/config.d.ts +50 -0
- package/dist/skill-loop/config.js +215 -0
- package/dist/skill-loop/curator.d.ts +18 -0
- package/dist/skill-loop/curator.js +232 -0
- package/dist/skill-loop/ledger.d.ts +39 -0
- package/dist/skill-loop/ledger.js +344 -0
- package/dist/skill-loop/proposals.d.ts +48 -0
- package/dist/skill-loop/proposals.js +290 -0
- package/dist/skill-loop/storage.d.ts +72 -0
- package/dist/skill-loop/storage.js +817 -0
- package/dist/skill-loop/time.d.ts +2 -0
- package/dist/skill-loop/time.js +23 -0
- package/dist/skill-loop/transaction.d.ts +62 -0
- package/dist/skill-loop/transaction.js +836 -0
- package/dist/skill-loop/usage.d.ts +31 -0
- package/dist/skill-loop/usage.js +146 -0
- package/dist/skill-observer.d.ts +22 -0
- package/dist/skill-observer.js +1154 -0
- package/dist/skill-renames.d.ts +5 -0
- package/dist/skill-renames.js +8 -0
- package/dist/skills.d.ts +307 -0
- package/dist/skills.js +450 -0
- package/dist/stable-identity.d.ts +14 -0
- package/dist/stable-identity.js +15 -0
- package/dist/state.d.ts +25 -0
- package/dist/state.js +38 -0
- package/dist/strict-json.d.ts +2 -0
- package/dist/strict-json.js +94 -0
- package/dist/tool-guards.d.ts +34 -0
- package/dist/tool-guards.js +210 -0
- package/dist/tool-kit.d.ts +32 -0
- package/dist/tool-kit.js +75 -0
- package/dist/tools.d.ts +43 -0
- package/dist/tools.js +381 -0
- package/dist/uiux-visual-catalog.d.ts +50 -0
- package/dist/uiux-visual-catalog.js +103 -0
- package/dist/user-facing-markdown.d.ts +5 -0
- package/dist/user-facing-markdown.js +93 -0
- package/dist/workflow-families.d.ts +16 -0
- package/dist/workflow-families.js +95 -0
- package/docs/assets/cover.webp +0 -0
- package/docs/assets/litopencode-continuity-1600.webp +0 -0
- package/docs/assets/litopencode-ignition-1600.webp +0 -0
- package/docs/assets/readme/badge-license.svg +1 -0
- package/docs/assets/readme/badge-version.svg +1 -0
- package/docs/assets/readme/litopencode-clay-icon.png +0 -0
- package/docs/assets/readme/litopencode-wordmark.svg +5 -0
- package/docs/lit-mark.md +46 -0
- package/docs/migration.md +162 -0
- package/docs/privacy.md +82 -0
- package/docs/reference-Ko-KR.md +309 -0
- package/docs/reference.md +444 -0
- package/output-styles/asd-ste100-ko.md +41 -0
- package/output-styles/asd-ste100.md +40 -0
- package/output-styles/eli5-ko.md +13 -0
- package/output-styles/eli5.md +11 -0
- package/package.json +57 -0
- package/qa/fixtures/litfamily-harness-speed-v1.json +38 -0
- package/qa/harness-speed-contract.mjs +209 -0
- package/qa/harness-speed-v2-contract.mjs +213 -0
- package/qa/harness-speed-verdict.mjs +105 -0
- package/skills/agent-roster/SKILL.md +262 -0
- package/skills/autoconference/LICENSE +21 -0
- package/skills/autoconference/PROVENANCE.md +20 -0
- package/skills/autoconference/SKILL.md +125 -0
- package/skills/autoconference/assets/conference_template.md +76 -0
- package/skills/autoconference/assets/report_template.md +53 -0
- package/skills/autoconference/assets/synthesis_template.md +39 -0
- package/skills/autoconference/modes/analyze.md +255 -0
- package/skills/autoconference/modes/core.md +112 -0
- package/skills/autoconference/modes/debate.md +373 -0
- package/skills/autoconference/modes/plan.md +310 -0
- package/skills/autoconference/modes/resume.md +48 -0
- package/skills/autoconference/modes/ship.md +57 -0
- package/skills/autoconference/modes/survey.md +109 -0
- package/skills/autoconference/references/agent-prompts.md +134 -0
- package/skills/autoconference/references/conference-protocol.md +102 -0
- package/skills/autoconference/references/convergence-guide.md +167 -0
- package/skills/autoconference/references/core-principles.md +83 -0
- package/skills/autoconference/references/crash-recovery.md +104 -0
- package/skills/autoconference/references/results-logging.md +198 -0
- package/skills/autoconference/references/upstream-family-contract.md +130 -0
- package/skills/autoconference/references/visualization-guide.md +105 -0
- package/skills/autoconference/scripts/check_conference.sh +371 -0
- package/skills/autoconference/scripts/init_conference.py +625 -0
- package/skills/autoconference/scripts/style_presets.py +104 -0
- package/skills/autoresearch/LICENSE +21 -0
- package/skills/autoresearch/PROVENANCE.md +20 -0
- package/skills/autoresearch/SKILL.md +131 -0
- package/skills/autoresearch/assets/report_template.md +50 -0
- package/skills/autoresearch/assets/research_template.md +38 -0
- package/skills/autoresearch/assets/results_template.tsv +1 -0
- package/skills/autoresearch/modes/core.md +216 -0
- package/skills/autoresearch/modes/debug.md +235 -0
- package/skills/autoresearch/modes/fix.md +173 -0
- package/skills/autoresearch/modes/learn.md +91 -0
- package/skills/autoresearch/modes/plan.md +291 -0
- package/skills/autoresearch/modes/predict.md +266 -0
- package/skills/autoresearch/modes/reason.md +170 -0
- package/skills/autoresearch/modes/scenario.md +164 -0
- package/skills/autoresearch/modes/security.md +282 -0
- package/skills/autoresearch/modes/ship.md +49 -0
- package/skills/autoresearch/references/core-principles.md +80 -0
- package/skills/autoresearch/references/evaluator-contract.md +126 -0
- package/skills/autoresearch/references/investigation-techniques.md +205 -0
- package/skills/autoresearch/references/owasp-checklist.md +161 -0
- package/skills/autoresearch/references/persona-templates.md +232 -0
- package/skills/autoresearch/references/results-logging.md +96 -0
- package/skills/autoresearch/references/scenario-dimensions.md +178 -0
- package/skills/autoresearch/references/stride-model.md +196 -0
- package/skills/autoresearch/references/stuck-detection.md +107 -0
- package/skills/autoresearch/references/type-checklists.md +163 -0
- package/skills/autoresearch/references/upstream-family-contract.md +125 -0
- package/skills/autoresearch/references/visualization-guide.md +95 -0
- package/skills/autoresearch/scripts/check_progress.sh +272 -0
- package/skills/autoresearch/scripts/init_research.py +330 -0
- package/skills/autoresearch/scripts/run_with_deadline.py +164 -0
- package/skills/autoresearch/scripts/style_presets.py +104 -0
- package/skills/browser-drive/SKILL.md +133 -0
- package/skills/browser-drive/references/snapshot-act-loop.md +37 -0
- package/skills/browser-drive/scripts/capability-probe.mjs +262 -0
- package/skills/comment-checker/SKILL.md +171 -0
- package/skills/debugging/SKILL.md +202 -0
- package/skills/debugging/references/README.md +15 -0
- package/skills/debugging/references/escalation.md +43 -0
- package/skills/debugging/references/runtimes/README.md +17 -0
- package/skills/debugging/references/runtimes/bundled-js-binary.md +44 -0
- package/skills/debugging/references/runtimes/go.md +37 -0
- package/skills/debugging/references/runtimes/native-binary.md +44 -0
- package/skills/debugging/references/runtimes/node.md +43 -0
- package/skills/debugging/references/runtimes/python.md +41 -0
- package/skills/debugging/references/runtimes/rust.md +37 -0
- package/skills/debugging/references/tools.md +72 -0
- package/skills/deep-interview/SKILL.md +201 -0
- package/skills/doctor-installer/SKILL.md +252 -0
- package/skills/durable-litgoal/SKILL.md +248 -0
- package/skills/frontend-ui-ux/SKILL.md +70 -0
- package/skills/frontend-ui-ux/data/LICENSE +21 -0
- package/skills/frontend-ui-ux/data/PROVENANCE.json +1088 -0
- package/skills/frontend-ui-ux/data/THIRD-PARTY-NOTICE.txt +14 -0
- package/skills/frontend-ui-ux/data/design-intelligence.json +1 -0
- package/skills/frontend-ui-ux/references/_canonical-corpus/ATTRIBUTION.md +217 -0
- package/skills/frontend-ui-ux/references/_canonical-corpus/LICENSE +21 -0
- package/skills/frontend-ui-ux/references/_canonical-corpus/LICENSE-Apache-2.0.txt +201 -0
- package/skills/frontend-ui-ux/references/_canonical-corpus/manifest.json +867 -0
- package/skills/frontend-ui-ux/references/adaptive-layout.md +85 -0
- package/skills/frontend-ui-ux/references/brand-and-imagery.md +79 -0
- package/skills/frontend-ui-ux/references/complete-contract.md +282 -0
- package/skills/frontend-ui-ux/references/composition.md +87 -0
- package/skills/frontend-ui-ux/references/creative-directions.md +83 -0
- package/skills/frontend-ui-ux/references/design/README.md +248 -0
- package/skills/frontend-ui-ux/references/design/_INDEX.md +191 -0
- package/skills/frontend-ui-ux/references/design/airbnb.md +393 -0
- package/skills/frontend-ui-ux/references/design/airtable.md +92 -0
- package/skills/frontend-ui-ux/references/design/apple.md +250 -0
- package/skills/frontend-ui-ux/references/design/aside.md +209 -0
- package/skills/frontend-ui-ux/references/design/binance.md +348 -0
- package/skills/frontend-ui-ux/references/design/bmw.md +183 -0
- package/skills/frontend-ui-ux/references/design/brutalist-skill.md +92 -0
- package/skills/frontend-ui-ux/references/design/bugatti.md +271 -0
- package/skills/frontend-ui-ux/references/design/cal.md +262 -0
- package/skills/frontend-ui-ux/references/design/claude.md +315 -0
- package/skills/frontend-ui-ux/references/design/clay.md +307 -0
- package/skills/frontend-ui-ux/references/design/clickhouse.md +284 -0
- package/skills/frontend-ui-ux/references/design/clone-from-url.md +65 -0
- package/skills/frontend-ui-ux/references/design/cohere.md +269 -0
- package/skills/frontend-ui-ux/references/design/coinbase.md +132 -0
- package/skills/frontend-ui-ux/references/design/composio.md +310 -0
- package/skills/frontend-ui-ux/references/design/cursor.md +312 -0
- package/skills/frontend-ui-ux/references/design/design-system-architecture.md +244 -0
- package/skills/frontend-ui-ux/references/design/elevenlabs.md +268 -0
- package/skills/frontend-ui-ux/references/design/expo.md +284 -0
- package/skills/frontend-ui-ux/references/design/ferrari.md +317 -0
- package/skills/frontend-ui-ux/references/design/figma.md +223 -0
- package/skills/frontend-ui-ux/references/design/framer.md +249 -0
- package/skills/frontend-ui-ux/references/design/gpt-tasteskill.md +74 -0
- package/skills/frontend-ui-ux/references/design/hashicorp.md +281 -0
- package/skills/frontend-ui-ux/references/design/ibm.md +335 -0
- package/skills/frontend-ui-ux/references/design/image-to-code-skill.md +1228 -0
- package/skills/frontend-ui-ux/references/design/imagegen-brandkit.md +798 -0
- package/skills/frontend-ui-ux/references/design/imagegen-frontend-mobile.md +1465 -0
- package/skills/frontend-ui-ux/references/design/imagegen-frontend-web.md +987 -0
- package/skills/frontend-ui-ux/references/design/intercom.md +149 -0
- package/skills/frontend-ui-ux/references/design/kraken.md +128 -0
- package/skills/frontend-ui-ux/references/design/lamborghini.md +291 -0
- package/skills/frontend-ui-ux/references/design/layout-skill.md +107 -0
- package/skills/frontend-ui-ux/references/design/lazyweb.md +77 -0
- package/skills/frontend-ui-ux/references/design/linear.app.md +370 -0
- package/skills/frontend-ui-ux/references/design/lovable.md +301 -0
- package/skills/frontend-ui-ux/references/design/mastercard.md +368 -0
- package/skills/frontend-ui-ux/references/design/meta.md +369 -0
- package/skills/frontend-ui-ux/references/design/minimalist-skill.md +85 -0
- package/skills/frontend-ui-ux/references/design/minimax.md +260 -0
- package/skills/frontend-ui-ux/references/design/mintlify.md +329 -0
- package/skills/frontend-ui-ux/references/design/miro.md +111 -0
- package/skills/frontend-ui-ux/references/design/mistral.ai.md +264 -0
- package/skills/frontend-ui-ux/references/design/mongodb.md +269 -0
- package/skills/frontend-ui-ux/references/design/nike.md +366 -0
- package/skills/frontend-ui-ux/references/design/notion.md +312 -0
- package/skills/frontend-ui-ux/references/design/nvidia.md +296 -0
- package/skills/frontend-ui-ux/references/design/ollama.md +270 -0
- package/skills/frontend-ui-ux/references/design/opencode.ai.md +284 -0
- package/skills/frontend-ui-ux/references/design/output-skill.md +49 -0
- package/skills/frontend-ui-ux/references/design/pinterest.md +233 -0
- package/skills/frontend-ui-ux/references/design/playstation.md +367 -0
- package/skills/frontend-ui-ux/references/design/posthog.md +259 -0
- package/skills/frontend-ui-ux/references/design/raycast.md +271 -0
- package/skills/frontend-ui-ux/references/design/react-dev-tooling-skill.md +230 -0
- package/skills/frontend-ui-ux/references/design/redesign-skill.md +178 -0
- package/skills/frontend-ui-ux/references/design/renault.md +314 -0
- package/skills/frontend-ui-ux/references/design/replicate.md +264 -0
- package/skills/frontend-ui-ux/references/design/resend.md +306 -0
- package/skills/frontend-ui-ux/references/design/revolut.md +188 -0
- package/skills/frontend-ui-ux/references/design/runwayml.md +247 -0
- package/skills/frontend-ui-ux/references/design/sanity.md +360 -0
- package/skills/frontend-ui-ux/references/design/sentry.md +265 -0
- package/skills/frontend-ui-ux/references/design/shopify.md +353 -0
- package/skills/frontend-ui-ux/references/design/soft-skill.md +98 -0
- package/skills/frontend-ui-ux/references/design/spacex.md +197 -0
- package/skills/frontend-ui-ux/references/design/spotify.md +249 -0
- package/skills/frontend-ui-ux/references/design/starbucks.md +583 -0
- package/skills/frontend-ui-ux/references/design/stitch-design-example.md +121 -0
- package/skills/frontend-ui-ux/references/design/stitch-skill.md +184 -0
- package/skills/frontend-ui-ux/references/design/stripe.md +325 -0
- package/skills/frontend-ui-ux/references/design/supabase.md +258 -0
- package/skills/frontend-ui-ux/references/design/superhuman.md +255 -0
- package/skills/frontend-ui-ux/references/design/taste-skill.md +1206 -0
- package/skills/frontend-ui-ux/references/design/tesla.md +289 -0
- package/skills/frontend-ui-ux/references/design/theverge.md +342 -0
- package/skills/frontend-ui-ux/references/design/together.ai.md +266 -0
- package/skills/frontend-ui-ux/references/design/uber.md +298 -0
- package/skills/frontend-ui-ux/references/design/vercel.md +313 -0
- package/skills/frontend-ui-ux/references/design/vodafone.md +426 -0
- package/skills/frontend-ui-ux/references/design/voltagent.md +326 -0
- package/skills/frontend-ui-ux/references/design/warp.md +256 -0
- package/skills/frontend-ui-ux/references/design/webflow.md +95 -0
- package/skills/frontend-ui-ux/references/design/wired.md +281 -0
- package/skills/frontend-ui-ux/references/design/wise.md +176 -0
- package/skills/frontend-ui-ux/references/design/x.ai.md +260 -0
- package/skills/frontend-ui-ux/references/design/zapier.md +331 -0
- package/skills/frontend-ui-ux/references/designpowers/EVIDENCE.md +97 -0
- package/skills/frontend-ui-ux/references/designpowers/README.md +48 -0
- package/skills/frontend-ui-ux/references/designpowers/UPSTREAM.md +80 -0
- package/skills/frontend-ui-ux/references/designpowers/lane-a-direction.md +64 -0
- package/skills/frontend-ui-ux/references/designpowers/lane-b-execution.md +65 -0
- package/skills/frontend-ui-ux/references/designpowers/lane-c-review.md +65 -0
- package/skills/frontend-ui-ux/references/designpowers/lane-d-memory.md +83 -0
- package/skills/frontend-ui-ux/references/designpowers/orchestration.md +80 -0
- package/skills/frontend-ui-ux/references/designpowers/routing.md +79 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/LICENSE +21 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/agents/accessibility-reviewer.md +83 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/agents/content-writer.md +132 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/agents/design-builder.md +109 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/agents/design-critic.md +89 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/agents/design-lead.md +113 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/agents/design-scout.md +78 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/agents/design-strategist.md +121 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/agents/heuristic-evaluator.md +268 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/agents/inspiration-scout.md +107 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/agents/motion-designer.md +120 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/skills/accessible-content/reference.md +101 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/skills/adaptive-interfaces/reference.md +109 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/skills/cognitive-accessibility/reference.md +107 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/skills/design-debate/reference.md +199 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/skills/design-debt-tracker/reference.md +174 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/skills/design-handoff/reference.md +125 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/skills/design-md/reference.md +106 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/skills/design-retrospective/reference.md +266 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/skills/design-review/reference.md +123 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/skills/design-system-alignment/reference.md +120 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/skills/designpowers-critique/reference.md +164 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/skills/heuristic-evaluation/reference.md +85 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/skills/inclusive-personas/reference.md +98 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/skills/inspiration-scouting/reference.md +165 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/skills/interaction-design/reference.md +122 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/skills/motion-choreography/reference.md +81 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/skills/research-planning/reference.md +96 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/skills/responsive-patterns/reference.md +77 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/skills/synthetic-user-testing/reference.md +192 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/skills/taste-feedback/reference.md +165 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/skills/taste-report/reference.md +78 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/skills/token-architecture/reference.md +75 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/skills/ui-composition/reference.md +117 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/skills/usability-testing/reference.md +78 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/skills/verification-before-shipping/reference.md +125 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/skills/voice-and-tone/reference.md +79 -0
- package/skills/frontend-ui-ux/references/designpowers/vendor/skills/writing-design-plans/reference.md +119 -0
- package/skills/frontend-ui-ux/references/evidence-review.md +103 -0
- package/skills/frontend-ui-ux/references/implementation-platforms.md +94 -0
- package/skills/frontend-ui-ux/references/inclusive-interface.md +85 -0
- package/skills/frontend-ui-ux/references/interaction-motion.md +93 -0
- package/skills/frontend-ui-ux/references/operating-lanes.md +80 -0
- package/skills/frontend-ui-ux/references/perfection/README.md +160 -0
- package/skills/frontend-ui-ux/references/perfection/react-perf-tooling.md +127 -0
- package/skills/frontend-ui-ux/references/performance-delivery.md +77 -0
- package/skills/frontend-ui-ux/references/product-direction.md +84 -0
- package/skills/frontend-ui-ux/references/redesign-playbook.md +88 -0
- package/skills/frontend-ui-ux/references/system-foundations.md +86 -0
- package/skills/frontend-ui-ux/references/taste-direction.md +55 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/README.md +659 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/data/charts.csv +26 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/data/colors.csv +162 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/data/icons.csv +106 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/data/landing.csv +35 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/data/products.csv +162 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/data/react-performance.csv +45 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/data/stacks/astro.csv +54 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/data/stacks/flutter.csv +53 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/data/stacks/html-tailwind.csv +56 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/data/stacks/jetpack-compose.csv +53 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/data/stacks/nextjs.csv +53 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/data/stacks/nuxt-ui.csv +51 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/data/stacks/nuxtjs.csv +59 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/data/stacks/react-native.csv +52 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/data/stacks/react.csv +54 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/data/stacks/shadcn.csv +61 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/data/stacks/svelte.csv +54 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/data/stacks/swiftui.csv +51 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/data/stacks/vue.csv +50 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/data/styles.csv +85 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/data/typography.csv +74 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/data/ui-reasoning.csv +162 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/data/ux-guidelines.csv +100 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/data/web-interface.csv +31 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/scripts/core.py +262 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/scripts/design_system.py +1148 -0
- package/skills/frontend-ui-ux/references/ui-ux-db/scripts/search.py +114 -0
- package/skills/frontend-ui-ux/references/visual-language.md +84 -0
- package/skills/frontend-ui-ux/references/visual-reconstruction.md +87 -0
- package/skills/frontend-ui-ux/schemas/design-contract-v1alpha1.json +570 -0
- package/skills/frontend-ui-ux/schemas/design-contract-v1beta1.json +32 -0
- package/skills/frontend-ui-ux/schemas/design-contract-v1beta2.json +34 -0
- package/skills/frontend-ui-ux/scripts/bounded-json.mjs +45 -0
- package/skills/frontend-ui-ux/scripts/canonical-json.mjs +26 -0
- package/skills/frontend-ui-ux/scripts/contract-error.mjs +15 -0
- package/skills/frontend-ui-ux/scripts/csv.mjs +64 -0
- package/skills/frontend-ui-ux/scripts/dataset.mjs +65 -0
- package/skills/frontend-ui-ux/scripts/design-contract.mjs +609 -0
- package/skills/frontend-ui-ux/scripts/import-design-intelligence.mjs +193 -0
- package/skills/frontend-ui-ux/scripts/retrieval.mjs +92 -0
- package/skills/frontend-ui-ux/scripts/stable-file-read.mjs +237 -0
- package/skills/frontend-ui-ux/scripts/stdin-json.mjs +16 -0
- package/skills/frontend-ui-ux/scripts/strict-json.mjs +102 -0
- package/skills/frontend-ui-ux/scripts/uiux.mjs +86 -0
- package/skills/frontend-ui-ux/scripts/verify-canonical-corpus.mjs +266 -0
- package/skills/lit-burnoff/SKILL.md +227 -0
- package/skills/lit-burnoff-file/SKILL.md +175 -0
- package/skills/lit-code/SKILL.md +266 -0
- package/skills/lit-code/references/README.md +18 -0
- package/skills/lit-code/references/go/README.md +12 -0
- package/skills/lit-code/references/go/concurrency.md +42 -0
- package/skills/lit-code/references/go/error-handling.md +47 -0
- package/skills/lit-code/references/go/testing.md +55 -0
- package/skills/lit-code/references/go/tooling.md +35 -0
- package/skills/lit-code/references/go/type-patterns.md +50 -0
- package/skills/lit-code/references/python/README.md +12 -0
- package/skills/lit-code/references/python/async.md +50 -0
- package/skills/lit-code/references/python/error-handling.md +44 -0
- package/skills/lit-code/references/python/testing.md +50 -0
- package/skills/lit-code/references/python/tooling.md +38 -0
- package/skills/lit-code/references/python/type-patterns.md +46 -0
- package/skills/lit-code/references/rust/README.md +12 -0
- package/skills/lit-code/references/rust/concurrency.md +45 -0
- package/skills/lit-code/references/rust/error-handling.md +43 -0
- package/skills/lit-code/references/rust/tooling.md +36 -0
- package/skills/lit-code/references/rust/type-patterns.md +46 -0
- package/skills/lit-code/references/rust/unsafe.md +47 -0
- package/skills/lit-code/references/typescript/README.md +11 -0
- package/skills/lit-code/references/typescript/error-handling.md +56 -0
- package/skills/lit-code/references/typescript/testing.md +42 -0
- package/skills/lit-code/references/typescript/tsconfig-strict.md +40 -0
- package/skills/lit-code/references/typescript/type-patterns.md +60 -0
- package/skills/lit-commit/SKILL.md +222 -0
- package/skills/lit-comprehend/SKILL.md +278 -0
- package/skills/lit-comprehend/assets/explainer-scaffold.html +104 -0
- package/skills/lit-comprehend/references/artifact-template.md +114 -0
- package/skills/lit-comprehend/references/micro-worlds.md +115 -0
- package/skills/lit-comprehend/scripts/verify-explainer.ts +339 -0
- package/skills/lit-crucible/SKILL.md +212 -0
- package/skills/lit-fetch/SKILL.md +242 -0
- package/skills/lit-handoff/SKILL.md +199 -0
- package/skills/lit-init/SKILL.md +214 -0
- package/skills/lit-korean/SKILL.md +231 -0
- package/skills/lit-plan/SKILL.md +351 -0
- package/skills/lit-plan/scripts/scaffold-plan.mjs +275 -0
- package/skills/lit-recap/SKILL.md +233 -0
- package/skills/lit-scientific-visualization/SKILL.md +175 -0
- package/skills/litresearch/SKILL.md +436 -0
- package/skills/litwork/SKILL.md +227 -0
- package/skills/lsp/SKILL.md +186 -0
- package/skills/lsp-setup/SKILL.md +187 -0
- package/skills/lsp-setup/references/README.md +40 -0
- package/skills/lsp-setup/references/bash.md +31 -0
- package/skills/lsp-setup/references/c-cpp.md +43 -0
- package/skills/lsp-setup/references/csharp.md +29 -0
- package/skills/lsp-setup/references/dart.md +25 -0
- package/skills/lsp-setup/references/elixir.md +30 -0
- package/skills/lsp-setup/references/go.md +33 -0
- package/skills/lsp-setup/references/haskell.md +27 -0
- package/skills/lsp-setup/references/java.md +28 -0
- package/skills/lsp-setup/references/julia.md +28 -0
- package/skills/lsp-setup/references/kotlin.md +25 -0
- package/skills/lsp-setup/references/lua.md +26 -0
- package/skills/lsp-setup/references/php.md +30 -0
- package/skills/lsp-setup/references/python.md +33 -0
- package/skills/lsp-setup/references/ruby.md +34 -0
- package/skills/lsp-setup/references/rust.md +34 -0
- package/skills/lsp-setup/references/swift.md +26 -0
- package/skills/lsp-setup/references/terraform.md +26 -0
- package/skills/lsp-setup/references/typescript.md +35 -0
- package/skills/lsp-setup/references/yaml.md +27 -0
- package/skills/lsp-setup/references/zig.md +28 -0
- package/skills/managed-skill-manifest.json +1386 -0
- package/skills/native-goal-verdict/SKILL.md +216 -0
- package/skills/refactor/SKILL.md +221 -0
- package/skills/reference-benchmark-claims/SKILL.md +204 -0
- package/skills/release-guardrails/SKILL.md +245 -0
- package/skills/review-work/SKILL.md +301 -0
- package/skills/rules/SKILL.md +196 -0
- package/skills/search-workflow-ideas/SKILL.md +223 -0
- package/skills/skill-observer/SKILL.md +148 -0
- package/skills/skill-observer/references/review-contract.md +95 -0
- package/skills/skill-rename-aliases.json +10 -0
- package/skills/start-work/SKILL.md +334 -0
- package/skills/structural-search/SKILL.md +234 -0
- package/skills/tool-guards/SKILL.md +223 -0
- package/skills/visual-qa/SKILL.md +61 -0
- package/skills/visual-qa/references/capture-playbook.md +105 -0
- package/skills/visual-qa/references/complete-contract.md +411 -0
- package/skills/visual-qa/schemas/evidence-manifest-v1alpha1.json +201 -0
- package/skills/visual-qa/schemas/evidence-manifest-v1beta1.json +141 -0
- package/skills/visual-qa/schemas/review-receipt-v1alpha1.json +113 -0
- package/skills/visual-qa/scripts/artifact.mjs +123 -0
- package/skills/visual-qa/scripts/bounded-json.mjs +47 -0
- package/skills/visual-qa/scripts/canonical-json.mjs +28 -0
- package/skills/visual-qa/scripts/capabilities.mjs +66 -0
- package/skills/visual-qa/scripts/contract-text.mjs +15 -0
- package/skills/visual-qa/scripts/design-contract.mjs +611 -0
- package/skills/visual-qa/scripts/evidence-evaluate.mjs +521 -0
- package/skills/visual-qa/scripts/evidence.mjs +271 -0
- package/skills/visual-qa/scripts/png-decode.mjs +146 -0
- package/skills/visual-qa/scripts/png.mjs +154 -0
- package/skills/visual-qa/scripts/review.mjs +188 -0
- package/skills/visual-qa/scripts/stdin-json.mjs +16 -0
- package/skills/visual-qa/scripts/strict-json.mjs +102 -0
- package/skills/visual-qa/scripts/tui.mjs +149 -0
- package/skills/visual-qa/scripts/visual-qa.mjs +90 -0
- package/skills/wikify/LICENSE +21 -0
- package/skills/wikify/PROVENANCE.md +18 -0
- package/skills/wikify/SKILL.md +176 -0
- package/skills/wikify/assets/home-template.md +44 -0
- package/skills/wikify/assets/maintenance-report-template.md +46 -0
- package/skills/wikify/assets/paper-source-note-template.md +137 -0
- package/skills/wikify/assets/source-note-template.md +45 -0
- package/skills/wikify/assets/wiki-rules-template.md +117 -0
- package/skills/wikify/modes/ingest.md +57 -0
- package/skills/wikify/modes/init.md +44 -0
- package/skills/wikify/modes/lint.md +60 -0
- package/skills/wikify/modes/query.md +38 -0
- package/skills/wikify/modes/save.md +45 -0
- package/skills/wikify/references-upstream-contract.md +758 -0
- package/skills/workflow-loop/SKILL.md +387 -0
- package/tools/check-pack-payload.mjs +410 -0
- package/tools/check-payload-substance.mjs +738 -0
- package/tools/check-version-lockstep.mjs +238 -0
- package/tools/gen-canonical-frontend-manifest.mjs +66 -0
- package/tools/gen-managed-skill-manifest.mjs +135 -0
- package/tools/harness-speed-local.mjs +261 -0
- package/tools/payload-reference-exemptions.json +49 -0
- package/tools/payload-substance-allowlist.json +46 -0
- package/tools/payload-substance-parity.json +571 -0
- package/tools/qa-real-surface-fixtures.mjs +428 -0
- package/tools/qa-real-surface-harness.mjs +173 -0
- package/tools/run-behavior-replacement-probes.mjs +296 -0
- package/tools/run-build.mjs +101 -0
- package/tools/run-harness-speed-local.mjs +52 -0
- package/tools/run-harness-speed-v2.mjs +36 -0
- package/tools/run-installed-resource-tamper-probe.mjs +62 -0
- package/tools/run-negative-gate-matrix.mjs +516 -0
- package/tools/run-rules-glob-differential.mjs +232 -0
- package/tools/run-typecheck.mjs +25 -0
- package/tools/run-uiux-visual-qa-scenarios.mjs +234 -0
- package/tools/run-wikify-surface-probe.mjs +170 -0
- package/tools/scan-legacy-tokens.mjs +431 -0
- package/tools/version-manifests.json +60 -0
- package/tsconfig.build.json +12 -0
- package/tsconfig.json +13 -0
- package/vendor/NOTICE.md +21 -0
- package/vendor/handoff/SKILL.md +199 -0
- package/vendor/handoff/evals/evals.json +154 -0
- package/vendor/handoff/examples/HANDOFF-example-generic-auth-refactor.md +97 -0
- package/vendor/handoff/templates/HANDOFF.md +121 -0
- package/vendor/licenses/022_handoff-MIT.txt +21 -0
- package/vendor/licenses/045_scientific-visualization-MIT.txt +21 -0
- package/vendor/provenance/022_handoff.md +19 -0
- package/vendor/provenance/045_scientific-visualization.md +36 -0
- package/vendor/scientific-visualization/SKILL.md +283 -0
- package/vendor/scientific-visualization/assets/color_palettes.py +197 -0
- package/vendor/scientific-visualization/assets/nature.mplstyle +75 -0
- package/vendor/scientific-visualization/assets/presentation.mplstyle +74 -0
- package/vendor/scientific-visualization/assets/publication.mplstyle +78 -0
- package/vendor/scientific-visualization/evals/evals.json +158 -0
- package/vendor/scientific-visualization/references/color_palettes.md +380 -0
- package/vendor/scientific-visualization/references/journal_requirements.md +359 -0
- package/vendor/scientific-visualization/references/matplotlib_examples.md +608 -0
- package/vendor/scientific-visualization/references/mdanalysis_martini_visualization.md +85 -0
- package/vendor/scientific-visualization/references/publication_guidelines.md +217 -0
- package/vendor/scientific-visualization/references/seaborn_for_publications.md +293 -0
- package/vendor/scientific-visualization/scripts/figure_export.py +238 -0
- package/vendor/scientific-visualization/scripts/style_presets.py +467 -0
- package/vendor/scientific-visualization/tests/test_figure_export.py +51 -0
- package/vendor/scientific-visualization/tests/test_style_presets.py +114 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { evaluateHarnessSpeedRecords } from "./harness-speed-verdict.mjs";
|
|
6
|
+
|
|
7
|
+
const SCHEMA = "litfamily.harness-speed/v1";
|
|
8
|
+
const SCENARIO_ID = "litfamily-speed-lit-activation-v1";
|
|
9
|
+
const PRODUCT = "litopencode";
|
|
10
|
+
const SCENARIO_BYTES = 1476;
|
|
11
|
+
const SCENARIO_SHA256 = "aaef5ba778532013248f0b5c0a9f958468786840595e48cb84851ab88bf2b4be";
|
|
12
|
+
const ARMS = ["baseline", "candidate", "control"];
|
|
13
|
+
const PHASES = ["B0", "S1", "S2"];
|
|
14
|
+
const COUNTERS = ["input_tokens", "cache_read_tokens", "cache_write_tokens", "output_tokens"];
|
|
15
|
+
const FAILURE_CODE_PATTERN = /^[A-Z][A-Z0-9_]{0,63}$/u;
|
|
16
|
+
const REQUIRED_FIELDS = [
|
|
17
|
+
"schema", "scenario_id", "product", "arm", "block", "order", "sequence", "phase",
|
|
18
|
+
"prompt_bytes", "prompt_sha256", "response_bytes", "response_sha256", "sentinel_match",
|
|
19
|
+
"route_observed", "output_policy_match", "correct", "failure_code", "timed_out",
|
|
20
|
+
"start_offset_ms", "first_content_offset_ms", "final_receipt_offset_ms", "exit_offset_ms",
|
|
21
|
+
...COUNTERS
|
|
22
|
+
];
|
|
23
|
+
const FORBIDDEN_FIELDS = new Set([
|
|
24
|
+
"prompt", "response", "transcript", "url", "request_id", "thread_id", "session_id",
|
|
25
|
+
"credential", "authorization", "cookie", "api_key"
|
|
26
|
+
]);
|
|
27
|
+
const UNAVAILABLE = "UNAVAILABLE";
|
|
28
|
+
|
|
29
|
+
export class HarnessSpeedContractError extends Error {
|
|
30
|
+
constructor(code, field = null) {
|
|
31
|
+
super(field === null ? code : `${code}:${field}`);
|
|
32
|
+
this.name = "HarnessSpeedContractError";
|
|
33
|
+
this.code = code;
|
|
34
|
+
this.field = field;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function reject(code, field = null) {
|
|
39
|
+
throw new HarnessSpeedContractError(code, field);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function isObject(value) {
|
|
43
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function assertPrivacy(value, location = "cohort") {
|
|
47
|
+
if (Array.isArray(value)) {
|
|
48
|
+
value.forEach((entry, index) => assertPrivacy(entry, `${location}[${index}]`));
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (!isObject(value)) return;
|
|
52
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
53
|
+
if (FORBIDDEN_FIELDS.has(key.toLowerCase())) reject("FORBIDDEN_FIELD", `${location}.${key}`);
|
|
54
|
+
assertPrivacy(entry, `${location}.${key}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function assertSafeCounter(value, field) {
|
|
59
|
+
if (value === UNAVAILABLE) return;
|
|
60
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value < 0) reject("INVALID_COUNTER", field);
|
|
61
|
+
if (!Number.isSafeInteger(value)) reject("UNSAFE_COUNTER", field);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function assertOffset(value, field, unavailableAllowed = false) {
|
|
65
|
+
if (unavailableAllowed && value === UNAVAILABLE) return;
|
|
66
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) reject("INVALID_TIME", field);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function phaseMap(scenario) {
|
|
70
|
+
if (!isObject(scenario) || !Array.isArray(scenario.records) || scenario.scenario_id !== SCENARIO_ID) {
|
|
71
|
+
reject("INVALID_SCENARIO");
|
|
72
|
+
}
|
|
73
|
+
return new Map(scenario.records.map((record) => [record.id, record]));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function validateRecord(record, index, scenarioPhases) {
|
|
77
|
+
const location = `records[${index}]`;
|
|
78
|
+
if (!isObject(record)) reject("INVALID_RECORD", location);
|
|
79
|
+
for (const field of REQUIRED_FIELDS) {
|
|
80
|
+
if (!Object.hasOwn(record, field)) reject("MISSING_RECORD_FIELD", `${location}.${field}`);
|
|
81
|
+
}
|
|
82
|
+
if (record.schema !== SCHEMA || record.scenario_id !== SCENARIO_ID || record.product !== PRODUCT) {
|
|
83
|
+
reject("RECORD_IDENTITY_MISMATCH", location);
|
|
84
|
+
}
|
|
85
|
+
if (!ARMS.includes(record.arm)) reject("INVALID_ARM", `${location}.arm`);
|
|
86
|
+
if (!Number.isInteger(record.block) || record.block < 1 || record.block > 6) reject("INVALID_BLOCK", location);
|
|
87
|
+
if (!Number.isInteger(record.order) || record.order < 1 || record.order > 3) reject("INVALID_ORDER", location);
|
|
88
|
+
if (!Number.isInteger(record.sequence) || record.sequence < 1 || record.sequence > 54) {
|
|
89
|
+
reject("INVALID_SEQUENCE", location);
|
|
90
|
+
}
|
|
91
|
+
const expected = scenarioPhases.get(record.phase);
|
|
92
|
+
if (!isObject(expected)) reject("INVALID_PHASE", `${location}.phase`);
|
|
93
|
+
if (record.prompt_bytes !== expected.prompt_bytes || record.prompt_sha256 !== expected.prompt_sha256) {
|
|
94
|
+
reject("PROMPT_IDENTITY_MISMATCH", location);
|
|
95
|
+
}
|
|
96
|
+
if (!Number.isSafeInteger(record.response_bytes) || record.response_bytes < 0) {
|
|
97
|
+
reject("INVALID_RESPONSE_IDENTITY", location);
|
|
98
|
+
}
|
|
99
|
+
if (typeof record.response_sha256 !== "string" || !/^[a-f0-9]{64}$/u.test(record.response_sha256)) {
|
|
100
|
+
reject("INVALID_RESPONSE_IDENTITY", location);
|
|
101
|
+
}
|
|
102
|
+
for (const field of ["sentinel_match", "route_observed", "output_policy_match", "correct", "timed_out"]) {
|
|
103
|
+
if (typeof record[field] !== "boolean") reject("INVALID_BOOLEAN", `${location}.${field}`);
|
|
104
|
+
}
|
|
105
|
+
if (record.failure_code !== null
|
|
106
|
+
&& (typeof record.failure_code !== "string" || !FAILURE_CODE_PATTERN.test(record.failure_code))) {
|
|
107
|
+
reject("INVALID_FAILURE_CODE", location);
|
|
108
|
+
}
|
|
109
|
+
const unsuccessful = !record.sentinel_match || !record.route_observed || !record.output_policy_match
|
|
110
|
+
|| record.timed_out || record.failure_code !== null;
|
|
111
|
+
if (unsuccessful && record.failure_code === null) reject("INVALID_FAILURE_CODE", location);
|
|
112
|
+
assertOffset(record.start_offset_ms, `${location}.start_offset_ms`);
|
|
113
|
+
assertOffset(record.first_content_offset_ms, `${location}.first_content_offset_ms`, true);
|
|
114
|
+
assertOffset(record.final_receipt_offset_ms, `${location}.final_receipt_offset_ms`);
|
|
115
|
+
assertOffset(record.exit_offset_ms, `${location}.exit_offset_ms`);
|
|
116
|
+
const first = record.first_content_offset_ms === UNAVAILABLE
|
|
117
|
+
? record.start_offset_ms
|
|
118
|
+
: record.first_content_offset_ms;
|
|
119
|
+
if (record.start_offset_ms > first || first > record.final_receipt_offset_ms
|
|
120
|
+
|| record.final_receipt_offset_ms > record.exit_offset_ms) reject("NON_MONOTONIC_TIME", location);
|
|
121
|
+
for (const field of COUNTERS) assertSafeCounter(record[field], `${location}.${field}`);
|
|
122
|
+
const derivedCorrect = !unsuccessful;
|
|
123
|
+
if (record.correct !== derivedCorrect) reject("CORRECTNESS_MISMATCH", location);
|
|
124
|
+
if (record.sentinel_match
|
|
125
|
+
&& (record.response_bytes !== expected.sentinel_bytes || record.response_sha256 !== expected.sentinel_sha256)) {
|
|
126
|
+
reject("SENTINEL_IDENTITY_MISMATCH", location);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function assertCohortShape(records) {
|
|
131
|
+
const seenArms = new Set(records.map((record) => record.arm));
|
|
132
|
+
for (const arm of ARMS) if (!seenArms.has(arm)) reject("MISSING_ARM", arm);
|
|
133
|
+
if (records.length !== 54) reject("INVALID_RECORD_COUNT");
|
|
134
|
+
const permutations = new Set();
|
|
135
|
+
for (let block = 1; block <= 6; block += 1) {
|
|
136
|
+
const blockArms = [];
|
|
137
|
+
for (let order = 1; order <= 3; order += 1) {
|
|
138
|
+
const start = ((block - 1) * 9) + ((order - 1) * 3);
|
|
139
|
+
const session = records.slice(start, start + 3);
|
|
140
|
+
const arm = session[0]?.arm;
|
|
141
|
+
if (!ARMS.includes(arm)) reject("INVALID_SESSION_ARM", `block-${block}-order-${order}`);
|
|
142
|
+
blockArms.push(arm);
|
|
143
|
+
session.forEach((record, phaseIndex) => {
|
|
144
|
+
const expectedSequence = start + phaseIndex + 1;
|
|
145
|
+
if (record.sequence !== expectedSequence) reject("INVALID_SEQUENCE", `sequence-${expectedSequence}`);
|
|
146
|
+
if (record.block !== block || record.order !== order || record.arm !== arm
|
|
147
|
+
|| record.phase !== PHASES[phaseIndex]) reject("INVALID_SESSION_ORDER", `sequence-${expectedSequence}`);
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
if (new Set(blockArms).size !== 3) reject("INVALID_BLOCK_PERMUTATION", `block-${block}`);
|
|
151
|
+
const permutation = blockArms.join(",");
|
|
152
|
+
if (permutations.has(permutation)) reject("DUPLICATE_PERMUTATION", `block-${block}`);
|
|
153
|
+
permutations.add(permutation);
|
|
154
|
+
}
|
|
155
|
+
if (permutations.size !== 6) reject("INCOMPLETE_PERMUTATIONS");
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function validateScenarioBytes(bytes) {
|
|
159
|
+
if (!Buffer.isBuffer(bytes)) reject("INVALID_SCENARIO_BYTES");
|
|
160
|
+
const digest = createHash("sha256").update(bytes).digest("hex");
|
|
161
|
+
if (bytes.length !== SCENARIO_BYTES || digest !== SCENARIO_SHA256) reject("STALE_SCENARIO");
|
|
162
|
+
const scenario = JSON.parse(bytes.toString("utf8"));
|
|
163
|
+
phaseMap(scenario);
|
|
164
|
+
return scenario;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function validateHarnessSpeedCohort(cohort, scenario) {
|
|
168
|
+
assertPrivacy(cohort);
|
|
169
|
+
if (!isObject(cohort) || cohort.schema !== SCHEMA || cohort.scenario_id !== SCENARIO_ID
|
|
170
|
+
|| cohort.product !== PRODUCT || !Array.isArray(cohort.records)) reject("COHORT_IDENTITY_MISMATCH");
|
|
171
|
+
const phases = phaseMap(scenario);
|
|
172
|
+
cohort.records.forEach((record, index) => validateRecord(record, index, phases));
|
|
173
|
+
assertCohortShape(cohort.records);
|
|
174
|
+
return evaluateHarnessSpeedRecords(cohort.records, reject);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export function scenarioSurfaceReceipt(bytes) {
|
|
178
|
+
const scenario = validateScenarioBytes(bytes);
|
|
179
|
+
return {
|
|
180
|
+
schema: "litfamily.harness-speed-surface/v1",
|
|
181
|
+
product: PRODUCT,
|
|
182
|
+
scenario_id: scenario.scenario_id,
|
|
183
|
+
fixture_bytes: bytes.length,
|
|
184
|
+
fixture_sha256: SCENARIO_SHA256,
|
|
185
|
+
phase_ids: scenario.records.map((record) => record.id),
|
|
186
|
+
provider_completions: 0,
|
|
187
|
+
raw_content_retained: false,
|
|
188
|
+
verdict: "PASS"
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function main(argv) {
|
|
193
|
+
if (argv.length !== 2 || argv[0] !== "--self-check") reject("INVALID_CLI_USAGE");
|
|
194
|
+
process.stdout.write(`${JSON.stringify(scenarioSurfaceReceipt(readFileSync(argv[1])))}\n`);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const invokedPath = process.argv[1];
|
|
198
|
+
if (invokedPath !== undefined && path.resolve(invokedPath) === fileURLToPath(import.meta.url)) {
|
|
199
|
+
try {
|
|
200
|
+
main(process.argv.slice(2));
|
|
201
|
+
} catch (error) {
|
|
202
|
+
if (error instanceof HarnessSpeedContractError) {
|
|
203
|
+
process.stderr.write(`${JSON.stringify({ verdict: "FAIL", code: error.code, field: error.field })}\n`);
|
|
204
|
+
process.exitCode = 1;
|
|
205
|
+
} else {
|
|
206
|
+
throw error;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
const schema = "litfamily.harness-speed-v2/comparison/v1";
|
|
4
|
+
const product = "litopencode";
|
|
5
|
+
const baselineHead = "4d4fa72648dc1b0277a4d8787768828b66ee3de8";
|
|
6
|
+
const baselineStatus = "09b2f68760bf47a94f0eb9bda264a9dc3f4117d77ef3f5c2f775083c712c2982";
|
|
7
|
+
const sourceArtifact = "301cdc5e3579637365c220abec961ebde1354fbdd37cbaf41f8c9e9f3171971f";
|
|
8
|
+
const fixtureHash = "aaef5ba778532013248f0b5c0a9f958468786840595e48cb84851ab88bf2b4be";
|
|
9
|
+
const phases = Object.freeze(["startup_config", "rules_transform", "no_route_floor", "activation_ledger", "s2_continuation", "local_total"]);
|
|
10
|
+
const arms = Object.freeze(["baseline", "candidate"]);
|
|
11
|
+
const guardNames = Object.freeze(["correctness", "route", "banner", "ledger", "body", "payload", "direct", "compaction"]);
|
|
12
|
+
const providerFields = Object.freeze(["input_tokens", "cache_read_tokens", "cache_write_tokens", "output_tokens"]);
|
|
13
|
+
const envelopeKeys = "baseline,blocks,candidate,context_bytes,fixture,guards,lever,product,provider,raw_content_retained,schema";
|
|
14
|
+
const proofKeys = "body_sha256,deterministic,host,loaded_sha256,mechanism,observed,surface";
|
|
15
|
+
const forbiddenFields = new Set(["prompt", "response", "transcript", "url", "request_id", "session_id", "credential", "authorization", "cookie", "api_key"]);
|
|
16
|
+
const misleadingFields = new Set(["verdict", "result", "claimedsuccess"]);
|
|
17
|
+
const sha256Pattern = /^[a-f0-9]{64}$/u;
|
|
18
|
+
|
|
19
|
+
export class HarnessSpeedV2ContractError extends Error {
|
|
20
|
+
constructor(code, field = null) {
|
|
21
|
+
super(field === null ? code : `${code}:${field}`);
|
|
22
|
+
Object.assign(this, { name: "HarnessSpeedV2ContractError", code, field });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function reject(code, field = null) {
|
|
27
|
+
throw new HarnessSpeedV2ContractError(code, field);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function isObject(value) {
|
|
31
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function assertPrivacy(value, location = "receipt") {
|
|
35
|
+
if (Array.isArray(value)) {
|
|
36
|
+
value.forEach((entry, index) => assertPrivacy(entry, `${location}[${index}]`));
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (!isObject(value)) return;
|
|
40
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
41
|
+
if (misleadingFields.has(key.toLowerCase().replace(/[_-]/gu, ""))) reject("MISLEADING_SUCCESS_FIELD", `${location}.${key}`);
|
|
42
|
+
if (forbiddenFields.has(key.toLowerCase())) reject("FORBIDDEN_FIELD", `${location}.${key}`);
|
|
43
|
+
assertPrivacy(entry, `${location}.${key}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function assertInteger(value, field, minimum = 0) {
|
|
48
|
+
if (!Number.isSafeInteger(value) || value < minimum) reject("INVALID_CANDIDATE_IDENTITY", field);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function assertHash(value, field, code) {
|
|
52
|
+
if (typeof value !== "string" || !sha256Pattern.test(value)) reject(code, field);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function assertIdentity(receipt) {
|
|
56
|
+
if (!isObject(receipt)) reject("INVALID_RECEIPT_IDENTITY");
|
|
57
|
+
if (Object.keys(receipt).sort().join(",") !== envelopeKeys) reject("UNEXPECTED_TOP_LEVEL_FIELD");
|
|
58
|
+
if (receipt.schema !== schema || receipt.product !== product) reject("INVALID_RECEIPT_IDENTITY");
|
|
59
|
+
if (!isObject(receipt.fixture) || receipt.fixture.bytes !== 1476 || receipt.fixture.sha256 !== fixtureHash) {
|
|
60
|
+
reject("FIXTURE_IDENTITY_MISMATCH");
|
|
61
|
+
}
|
|
62
|
+
if (!isObject(receipt.baseline) || receipt.baseline.source !== "frozen_repaired") reject("INVALID_BASELINE_SOURCE");
|
|
63
|
+
if (receipt.baseline.head !== baselineHead) reject("BASELINE_HEAD_MISMATCH");
|
|
64
|
+
if (receipt.baseline.source_artifact_sha256 !== sourceArtifact) reject("BASELINE_SOURCE_ARTIFACT_MISMATCH");
|
|
65
|
+
if (receipt.baseline.status_sha256 !== baselineStatus
|
|
66
|
+
|| receipt.baseline.status_bytes !== 474 || receipt.baseline.status_records !== 14) {
|
|
67
|
+
reject("BASELINE_STATUS_MISMATCH");
|
|
68
|
+
}
|
|
69
|
+
assertHash(receipt.baseline.artifact_sha256, "baseline.artifact_sha256", "INVALID_BASELINE_IDENTITY");
|
|
70
|
+
if (!isObject(receipt.candidate)) reject("INVALID_CANDIDATE_IDENTITY");
|
|
71
|
+
if (receipt.candidate.head !== baselineHead) reject("CANDIDATE_HEAD_MISMATCH");
|
|
72
|
+
if (receipt.candidate.base_source_artifact_sha256 !== sourceArtifact) reject("CANDIDATE_BASE_SOURCE_ARTIFACT_MISMATCH");
|
|
73
|
+
assertHash(receipt.candidate.source_artifact_sha256, "candidate.source_artifact_sha256", "INVALID_CANDIDATE_SOURCE_ARTIFACT");
|
|
74
|
+
if (receipt.candidate.source_artifact_sha256 === sourceArtifact) reject("CANDIDATE_SOURCE_ARTIFACT_NOT_DISTINCT");
|
|
75
|
+
assertHash(receipt.candidate.artifact_sha256, "candidate.artifact_sha256", "INVALID_CANDIDATE_IDENTITY");
|
|
76
|
+
assertHash(receipt.candidate.status_sha256, "candidate.status_sha256", "INVALID_CANDIDATE_IDENTITY");
|
|
77
|
+
if (receipt.candidate.artifact_sha256 === receipt.baseline.artifact_sha256) reject("CANDIDATE_ARTIFACT_NOT_DISTINCT");
|
|
78
|
+
if (receipt.candidate.status_sha256 === receipt.baseline.status_sha256) reject("CANDIDATE_STATUS_NOT_DISTINCT");
|
|
79
|
+
assertInteger(receipt.candidate.status_bytes, "candidate.status_bytes", 1);
|
|
80
|
+
assertInteger(receipt.candidate.status_records, "candidate.status_records", 0);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function assertSamples(value, field) {
|
|
84
|
+
if (!Array.isArray(value) || value.length !== 5) reject("INVALID_SAMPLE_COUNT", field);
|
|
85
|
+
value.forEach((sample, index) => {
|
|
86
|
+
if (!isObject(sample) || Object.keys(sample).sort().join(",") !== "index,value_ms"
|
|
87
|
+
|| typeof sample.value_ms !== "number" || !Number.isFinite(sample.value_ms) || sample.value_ms < 0) {
|
|
88
|
+
reject("INVALID_SAMPLE", `${field}[${index}]`);
|
|
89
|
+
}
|
|
90
|
+
if (sample.index !== index + 1) reject("INVALID_SAMPLE_INDEX", `${field}[${index}]`);
|
|
91
|
+
});
|
|
92
|
+
return value.map((sample) => sample.value_ms);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function collectSamples(receipt) {
|
|
96
|
+
if (!Array.isArray(receipt.blocks) || receipt.blocks.length !== 6) reject("INVALID_BLOCK_COUNT");
|
|
97
|
+
const collected = Object.fromEntries(arms.map((arm) => [arm, Object.fromEntries(phases.map((phase) => [phase, []]))]));
|
|
98
|
+
receipt.blocks.forEach((block, index) => {
|
|
99
|
+
const expectedOrder = index % 2 === 0 ? arms : [...arms].reverse();
|
|
100
|
+
if (!isObject(block) || block.block !== index + 1) reject("INVALID_BLOCK_ID", `blocks[${index}]`);
|
|
101
|
+
if (!Array.isArray(block.order) || block.order.length !== 2
|
|
102
|
+
|| block.order.some((arm, orderIndex) => arm !== expectedOrder[orderIndex])) reject("INVALID_ARM_ORDER", `blocks[${index}]`);
|
|
103
|
+
for (const arm of arms) {
|
|
104
|
+
if (!isObject(block.arms?.[arm])) reject("INVALID_ARM", `blocks[${index}].${arm}`);
|
|
105
|
+
for (const phase of phases) {
|
|
106
|
+
const values = assertSamples(block.arms[arm][phase], `blocks[${index}].${arm}.${phase}`);
|
|
107
|
+
collected[arm][phase].push(...values);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
return collected;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function nearestRank(values, percentile) {
|
|
115
|
+
const sorted = [...values].sort((left, right) => left - right);
|
|
116
|
+
return sorted[Math.ceil(percentile * sorted.length) - 1];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function summarize(collected) {
|
|
120
|
+
return Object.fromEntries(phases.map((phase) => {
|
|
121
|
+
const baseline = collected.baseline[phase];
|
|
122
|
+
const candidate = collected.candidate[phase];
|
|
123
|
+
const baselineP95 = nearestRank(baseline, 0.95);
|
|
124
|
+
const candidateP95 = nearestRank(candidate, 0.95);
|
|
125
|
+
const gain = baselineP95 > 0 ? (baselineP95 - candidateP95) / baselineP95 : null;
|
|
126
|
+
return [phase, {
|
|
127
|
+
baseline_p50_ms: nearestRank(baseline, 0.5),
|
|
128
|
+
baseline_p95_ms: baselineP95,
|
|
129
|
+
candidate_p50_ms: nearestRank(candidate, 0.5),
|
|
130
|
+
candidate_p95_ms: candidateP95,
|
|
131
|
+
gain_ratio: gain
|
|
132
|
+
}];
|
|
133
|
+
}));
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function assertPerformance(receipt, metrics) {
|
|
137
|
+
const aggregate = metrics.local_total;
|
|
138
|
+
if (aggregate.candidate_p50_ms > aggregate.baseline_p50_ms) reject("AGGREGATE_P50_REGRESSION");
|
|
139
|
+
if (aggregate.candidate_p95_ms > aggregate.baseline_p95_ms) reject("AGGREGATE_P95_REGRESSION");
|
|
140
|
+
for (const phase of phases) {
|
|
141
|
+
if (metrics[phase].candidate_p95_ms > metrics[phase].baseline_p95_ms) reject("PHASE_P95_REGRESSION", phase);
|
|
142
|
+
}
|
|
143
|
+
const early = receipt.blocks.slice(0, 3).flatMap((block) => block.arms.baseline.local_total.map((sample) => sample.value_ms));
|
|
144
|
+
const late = receipt.blocks.slice(3).flatMap((block) => block.arms.baseline.local_total.map((sample) => sample.value_ms));
|
|
145
|
+
const earlyP95 = nearestRank(early, 0.95);
|
|
146
|
+
const drift = earlyP95 > 0 ? Math.abs(nearestRank(late, 0.95) - earlyP95) / earlyP95 : null;
|
|
147
|
+
if (drift === null || drift > 0.20) reject("BASELINE_DRIFT");
|
|
148
|
+
if (!isObject(receipt.lever)) reject("INVALID_LEVER_KIND");
|
|
149
|
+
if (receipt.lever.kind === "latency") {
|
|
150
|
+
if (!phases.includes(receipt.lever.phase)) reject("INVALID_LEVER_PHASE");
|
|
151
|
+
if (metrics[receipt.lever.phase].gain_ratio === null || metrics[receipt.lever.phase].gain_ratio < 0.15) {
|
|
152
|
+
reject("SELECTED_LATENCY_GAIN_NOT_MET");
|
|
153
|
+
}
|
|
154
|
+
} else if (receipt.lever.kind !== "context_bytes") reject("INVALID_LEVER_KIND");
|
|
155
|
+
return drift;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function assertSemanticAndProvider(receipt) {
|
|
159
|
+
if (!isObject(receipt.guards)) reject("SEMANTIC_GUARD_FAILED");
|
|
160
|
+
for (const name of guardNames) {
|
|
161
|
+
const guard = receipt.guards[name];
|
|
162
|
+
if (!isObject(guard) || guard.baseline !== true || guard.candidate !== true) reject("SEMANTIC_GUARD_FAILED", name);
|
|
163
|
+
}
|
|
164
|
+
if (!isObject(receipt.provider) || receipt.provider.calls !== 0 || receipt.provider.completions !== 0) {
|
|
165
|
+
reject("PROVIDER_ACTIVITY_OBSERVED");
|
|
166
|
+
}
|
|
167
|
+
for (const field of providerFields) {
|
|
168
|
+
if (receipt.provider[field] !== "UNAVAILABLE") reject("PROVIDER_FIELD_NOT_UNAVAILABLE", field);
|
|
169
|
+
}
|
|
170
|
+
if (receipt.raw_content_retained !== false) reject("RAW_CONTENT_RETAINED");
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function assertContext(receipt) {
|
|
174
|
+
const context = receipt.context_bytes;
|
|
175
|
+
if (!isObject(context) || !Number.isSafeInteger(context.baseline) || context.baseline <= 0
|
|
176
|
+
|| !Number.isSafeInteger(context.candidate) || context.candidate < 0) reject("INVALID_CONTEXT_BYTES");
|
|
177
|
+
const reduction = (context.baseline - context.candidate) / context.baseline;
|
|
178
|
+
if (reduction > 0) {
|
|
179
|
+
const proof = receipt.lever?.proof;
|
|
180
|
+
if (!isObject(proof) || Object.keys(proof).sort().join(",") !== proofKeys
|
|
181
|
+
|| proof.mechanism !== "opencode_pre_request" || proof.observed !== true || proof.deterministic !== true
|
|
182
|
+
|| proof.host !== "opencode" || proof.surface !== "pre_request"
|
|
183
|
+
|| !sha256Pattern.test(proof.body_sha256 ?? "") || proof.loaded_sha256 !== proof.body_sha256) {
|
|
184
|
+
reject("DETERMINISTIC_LOADER_PROOF_REQUIRED");
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
if (receipt.lever?.kind === "context_bytes" && reduction < 0.25) reject("CONTEXT_REDUCTION_NOT_MET");
|
|
188
|
+
return reduction;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export function validateV2Comparison(receipt) {
|
|
192
|
+
assertPrivacy(receipt);
|
|
193
|
+
assertIdentity(receipt);
|
|
194
|
+
const collected = collectSamples(receipt);
|
|
195
|
+
const metrics = summarize(collected);
|
|
196
|
+
const baselineDrift = assertPerformance(receipt, metrics);
|
|
197
|
+
assertSemanticAndProvider(receipt);
|
|
198
|
+
const contextReduction = assertContext(receipt);
|
|
199
|
+
return {
|
|
200
|
+
schema: "litfamily.harness-speed-v2/verdict/v1",
|
|
201
|
+
product,
|
|
202
|
+
verdict: "PASS",
|
|
203
|
+
cohort: { blocks: 6, samples_per_arm_phase: 30 },
|
|
204
|
+
metrics: { aggregate: metrics.local_total, phases: metrics, baseline_drift_ratio: baselineDrift, context_reduction_ratio: contextReduction },
|
|
205
|
+
provider: { calls: 0, completions: 0, fields: "UNAVAILABLE" },
|
|
206
|
+
raw_content_retained: false
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export function validateV2FixtureBytes(bytes) {
|
|
211
|
+
const digest = createHash("sha256").update(bytes).digest("hex");
|
|
212
|
+
if (bytes.length !== 1476 || digest !== fixtureHash) reject("FIXTURE_IDENTITY_MISMATCH");
|
|
213
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
const ARMS = ["baseline", "candidate", "control"];
|
|
2
|
+
const UNAVAILABLE = "UNAVAILABLE";
|
|
3
|
+
|
|
4
|
+
function nearestRank(values, percentile, reject) {
|
|
5
|
+
if (values.length === 0) reject("EMPTY_PERCENTILE");
|
|
6
|
+
const sorted = [...values].sort((left, right) => left - right);
|
|
7
|
+
return sorted[Math.max(0, Math.ceil(percentile * sorted.length) - 1)];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function e2e(record) {
|
|
11
|
+
return record.exit_offset_ms - record.start_offset_ms;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function numericSum(records, field, reject) {
|
|
15
|
+
let total = 0;
|
|
16
|
+
for (const record of records) {
|
|
17
|
+
const value = record[field];
|
|
18
|
+
if (value === UNAVAILABLE) return UNAVAILABLE;
|
|
19
|
+
total += value;
|
|
20
|
+
if (!Number.isSafeInteger(total)) reject("UNSAFE_COUNTER_SUM", field);
|
|
21
|
+
}
|
|
22
|
+
return total;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function armDiagnostics(records, reject) {
|
|
26
|
+
const input = numericSum(records, "input_tokens", reject);
|
|
27
|
+
const cache = numericSum(records, "cache_read_tokens", reject);
|
|
28
|
+
const compatible = records.every((record) => typeof record.input_tokens === "number"
|
|
29
|
+
&& typeof record.cache_read_tokens === "number" && record.cache_read_tokens <= record.input_tokens);
|
|
30
|
+
return {
|
|
31
|
+
cache_read_share: typeof input === "number" && input > 0 && typeof cache === "number" ? cache / input : UNAVAILABLE,
|
|
32
|
+
uncached_input_per_correct_turn: compatible && records.length > 0
|
|
33
|
+
? records.reduce((total, record) => total + record.input_tokens - record.cache_read_tokens, 0) / records.length
|
|
34
|
+
: UNAVAILABLE
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function evaluateHarnessSpeedRecords(records, reject) {
|
|
39
|
+
const measured = Object.fromEntries(ARMS.map((arm) => [arm,
|
|
40
|
+
records.filter((record) => record.arm === arm && record.phase !== "B0")]));
|
|
41
|
+
const warmups = Object.fromEntries(ARMS.map((arm) => [arm,
|
|
42
|
+
records.filter((record) => record.arm === arm && record.phase === "B0")]));
|
|
43
|
+
const durations = Object.fromEntries(ARMS.map((arm) => [arm, measured[arm].map(e2e)]));
|
|
44
|
+
const summaries = Object.fromEntries(ARMS.map((arm) => [arm, {
|
|
45
|
+
warmups_correct: warmups[arm].filter((record) => record.correct).length,
|
|
46
|
+
measured_correct: measured[arm].filter((record) => record.correct).length,
|
|
47
|
+
p50_ms: nearestRank(durations[arm], 0.5, reject),
|
|
48
|
+
p95_ms: nearestRank(durations[arm], 0.95, reject),
|
|
49
|
+
total_input_tokens: numericSum(measured[arm], "input_tokens", reject)
|
|
50
|
+
}]));
|
|
51
|
+
const ratios = measured.candidate.map((candidate) => {
|
|
52
|
+
const baseline = measured.baseline.find((record) => record.block === candidate.block && record.phase === candidate.phase);
|
|
53
|
+
if (baseline === undefined || e2e(baseline) <= 0) reject("INVALID_PAIR", `${candidate.block}-${candidate.phase}`);
|
|
54
|
+
return e2e(candidate) / e2e(baseline);
|
|
55
|
+
});
|
|
56
|
+
const earlyControl = durations.control.slice(0, 6);
|
|
57
|
+
const lateControl = durations.control.slice(6);
|
|
58
|
+
const earlyP95 = nearestRank(earlyControl, 0.95, reject);
|
|
59
|
+
if (earlyP95 <= 0) reject("INVALID_CONTROL_BASELINE");
|
|
60
|
+
const pairedMedianRatio = nearestRank(ratios, 0.5, reject);
|
|
61
|
+
const controlDriftRatio = Math.abs(nearestRank(lateControl, 0.95, reject) - earlyP95) / earlyP95;
|
|
62
|
+
const allCorrect = ARMS.every((arm) => summaries[arm].warmups_correct === 6
|
|
63
|
+
&& summaries[arm].measured_correct === 12);
|
|
64
|
+
const baselineInput = summaries.baseline.total_input_tokens;
|
|
65
|
+
const candidateInput = summaries.candidate.total_input_tokens;
|
|
66
|
+
const antiPadding = typeof baselineInput === "number" && typeof candidateInput === "number"
|
|
67
|
+
? candidateInput <= baselineInput : UNAVAILABLE;
|
|
68
|
+
const gates = {
|
|
69
|
+
correctness: allCorrect,
|
|
70
|
+
candidate_p95: summaries.candidate.p95_ms <= summaries.baseline.p95_ms * 0.85,
|
|
71
|
+
candidate_p50: summaries.candidate.p50_ms <= summaries.baseline.p50_ms,
|
|
72
|
+
paired_ratio: pairedMedianRatio <= 0.85,
|
|
73
|
+
control_drift: controlDriftRatio <= 0.20,
|
|
74
|
+
anti_padding: antiPadding
|
|
75
|
+
};
|
|
76
|
+
const candidateCache = numericSum(measured.candidate, "cache_read_tokens", reject);
|
|
77
|
+
const cacheCompatible = [...measured.baseline, ...measured.candidate].every((record) =>
|
|
78
|
+
typeof record.input_tokens === "number" && typeof record.cache_read_tokens === "number"
|
|
79
|
+
&& record.cache_read_tokens <= record.input_tokens);
|
|
80
|
+
const latencySaved = cacheCompatible && typeof candidateCache === "number" && candidateCache > 0
|
|
81
|
+
? (durations.baseline.reduce((sum, value) => sum + value, 0)
|
|
82
|
+
- durations.candidate.reduce((sum, value) => sum + value, 0)) / (candidateCache / 1000)
|
|
83
|
+
: UNAVAILABLE;
|
|
84
|
+
const reasonCodes = [];
|
|
85
|
+
if (!gates.correctness) reasonCodes.push("CORRECTNESS_FAILED");
|
|
86
|
+
if (!gates.candidate_p95) reasonCodes.push("CANDIDATE_P95_TARGET_NOT_MET");
|
|
87
|
+
if (!gates.candidate_p50) reasonCodes.push("CANDIDATE_P50_REGRESSION");
|
|
88
|
+
if (!gates.paired_ratio) reasonCodes.push("PAIRED_RATIO_TARGET_NOT_MET");
|
|
89
|
+
if (!gates.control_drift) reasonCodes.push("ENVIRONMENT_DRIFT");
|
|
90
|
+
if (gates.anti_padding === false) reasonCodes.push("INPUT_PADDING");
|
|
91
|
+
if (gates.anti_padding === UNAVAILABLE) reasonCodes.push("INPUT_TOKENS_UNAVAILABLE");
|
|
92
|
+
return {
|
|
93
|
+
verdict: reasonCodes.length === 0 ? "PASS"
|
|
94
|
+
: gates.anti_padding === UNAVAILABLE && reasonCodes.length === 1 ? UNAVAILABLE : "FAIL",
|
|
95
|
+
reason_codes: reasonCodes,
|
|
96
|
+
cohort: { records: 54, sessions_per_arm: 6, measured_turns_per_arm: 12 },
|
|
97
|
+
arms: summaries,
|
|
98
|
+
metrics: { paired_median_ratio: pairedMedianRatio, control_drift_ratio: controlDriftRatio },
|
|
99
|
+
gates,
|
|
100
|
+
diagnostics: {
|
|
101
|
+
cache: Object.fromEntries(ARMS.map((arm) => [arm, armDiagnostics(measured[arm], reject)])),
|
|
102
|
+
latency_saved_ms_per_1k_cache_read_tokens: latencySaved
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
}
|