@geraldmaron/construct 1.0.12 → 1.0.15
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/README.md +14 -2
- package/bin/construct +262 -14
- package/bin/construct-postinstall.mjs +23 -2
- package/commands/build/feature.md +0 -6
- package/commands/build/fix.md +0 -6
- package/commands/design/access.md +0 -6
- package/commands/design/flow.md +0 -6
- package/commands/design/ui.md +0 -6
- package/commands/measure/experiment.md +0 -6
- package/commands/measure/metrics.md +0 -6
- package/commands/measure/results.md +0 -6
- package/commands/plan/api.md +0 -6
- package/commands/plan/challenge.md +0 -6
- package/commands/plan/decide.md +0 -6
- package/commands/plan/feature.md +0 -7
- package/commands/plan/requirements.md +0 -6
- package/commands/remember/context.md +0 -6
- package/commands/remember/handoff.md +0 -6
- package/commands/remember/runbook.md +0 -6
- package/commands/review/code.md +0 -6
- package/commands/review/quality.md +0 -6
- package/commands/review/security.md +0 -6
- package/commands/ship/ready.md +0 -6
- package/commands/ship/release.md +0 -6
- package/commands/ship/status.md +0 -6
- package/commands/understand/docs.md +0 -6
- package/commands/understand/research.md +0 -6
- package/commands/understand/this.md +0 -6
- package/commands/understand/why.md +0 -6
- package/commands/work/clean.md +0 -6
- package/commands/work/drive.md +0 -6
- package/commands/work/optimize-prompts.md +0 -6
- package/commands/work/parallel-review.md +0 -6
- package/lib/auto-docs.mjs +11 -7
- package/lib/beads-client.mjs +19 -1
- package/lib/comment-lint.mjs +5 -1
- package/lib/context-state.mjs +15 -3
- package/lib/contracts/validate.mjs +54 -10
- package/lib/contracts/violation-log.mjs +154 -0
- package/lib/dashboard-static.mjs +7 -4
- package/lib/doc-stamp.mjs +16 -0
- package/lib/docs-verify.mjs +1 -8
- package/lib/doctor/watchers/bd-watch.mjs +6 -2
- package/lib/document-extract/docling-client.mjs +114 -0
- package/lib/document-extract/docling-sidecar.py +122 -0
- package/lib/document-extract/whisper-client.mjs +79 -0
- package/lib/document-extract.mjs +73 -8
- package/lib/document-ingest.mjs +26 -4
- package/lib/embed/daemon.mjs +26 -1
- package/lib/embed/docs-lifecycle.mjs +19 -0
- package/lib/embed/inbox.mjs +85 -2
- package/lib/embed/recommendation-store.mjs +29 -0
- package/lib/flavors/loader.mjs +1 -1
- package/lib/gates-audit.mjs +18 -12
- package/lib/handoffs/contract.mjs +2 -2
- package/lib/hooks/_lib/input.mjs +52 -0
- package/lib/hooks/adaptive-lint.mjs +4 -0
- package/lib/hooks/agent-tracker.mjs +59 -15
- package/lib/hooks/audit-reads.mjs +83 -42
- package/lib/hooks/audit-trail.mjs +28 -18
- package/lib/hooks/bash-output-logger.mjs +8 -2
- package/lib/hooks/block-no-verify.mjs +4 -0
- package/lib/hooks/ci-status-check.mjs +4 -0
- package/lib/hooks/comment-lint.mjs +6 -4
- package/lib/hooks/config-protection.mjs +4 -0
- package/lib/hooks/context-watch.mjs +4 -0
- package/lib/hooks/context-window-recovery.mjs +4 -0
- package/lib/hooks/dep-audit.mjs +12 -5
- package/lib/hooks/doc-coupling-check.mjs +5 -1
- package/lib/hooks/edit-accumulator.mjs +25 -10
- package/lib/hooks/edit-error-recovery.mjs +4 -0
- package/lib/hooks/edit-guard.mjs +4 -0
- package/lib/hooks/guard-bash.mjs +4 -0
- package/lib/hooks/mcp-audit.mjs +4 -0
- package/lib/hooks/mcp-health-check.mjs +4 -0
- package/lib/hooks/model-fallback.mjs +7 -11
- package/lib/hooks/policy-engine.mjs +4 -0
- package/lib/hooks/post-merge-docs-check.mjs +4 -0
- package/lib/hooks/post-merge-tracking.mjs +82 -0
- package/lib/hooks/pre-compact.mjs +4 -0
- package/lib/hooks/pre-push-gate.mjs +84 -231
- package/lib/hooks/proactive-activation.mjs +5 -2
- package/lib/hooks/readme-age-check.mjs +4 -0
- package/lib/hooks/registry-sync.mjs +35 -20
- package/lib/hooks/rule-verifier.mjs +3 -0
- package/lib/hooks/scan-secrets.mjs +4 -0
- package/lib/hooks/session-optimize.mjs +4 -0
- package/lib/hooks/session-reflect.mjs +4 -0
- package/lib/hooks/session-start.mjs +49 -2
- package/lib/hooks/session-tracking-refresh.mjs +70 -0
- package/lib/hooks/stop-notify.mjs +13 -2
- package/lib/hooks/stop-typecheck.mjs +4 -0
- package/lib/hooks/test-watch.mjs +8 -4
- package/lib/ingest/chunker.mjs +94 -0
- package/lib/ingest/pipeline.mjs +53 -0
- package/lib/ingest/store.mjs +82 -0
- package/lib/init-unified.mjs +90 -23
- package/lib/intake/attribution.mjs +77 -0
- package/lib/intake/intake-config.mjs +3 -0
- package/lib/intake/manifest.mjs +107 -0
- package/lib/intake/poll-lock.mjs +136 -0
- package/lib/intake/prepare.mjs +42 -4
- package/lib/knowledge/search.mjs +12 -0
- package/lib/logging/rotate.mjs +394 -0
- package/lib/mcp/server.mjs +142 -1
- package/lib/mcp/tools/project.mjs +2 -2
- package/lib/mcp/tools/skills.mjs +6 -3
- package/lib/mcp/tools/telemetry.mjs +1 -1
- package/lib/mcp/tools/workflow.mjs +6 -2
- package/lib/observation-store.mjs +14 -5
- package/lib/ollama-manager.mjs +32 -28
- package/lib/opencode-config.mjs +10 -3
- package/lib/orchestration/routing-tables.mjs +176 -0
- package/lib/orchestration-policy.mjs +18 -106
- package/lib/parity.mjs +48 -7
- package/lib/profiles/lifecycle.mjs +19 -1
- package/lib/project-init-shared.mjs +11 -5
- package/lib/project-root.mjs +104 -0
- package/lib/prompt-composer.js +11 -1
- package/lib/roles/catalog.mjs +1 -1
- package/lib/roles/event-bus.mjs +29 -9
- package/lib/roles/router.mjs +8 -7
- package/lib/runtime/uv-bootstrap.mjs +129 -0
- package/lib/runtime/whisper-bootstrap.mjs +102 -0
- package/lib/server/index.mjs +53 -10
- package/lib/server/static/index.html +1 -15
- package/lib/specialists/postconditions.mjs +1 -1
- package/lib/status.mjs +1 -1
- package/lib/storage/backup.mjs +2 -2
- package/lib/sync/skill-frontmatter.mjs +113 -21
- package/lib/telemetry/intent-verifications.mjs +16 -3
- package/lib/telemetry/skill-calls.mjs +12 -3
- package/lib/tracking-surfaces.mjs +377 -0
- package/lib/validators/skills.mjs +86 -54
- package/lib/worker/trace.mjs +19 -2
- package/package.json +10 -6
- package/personas/construct.md +4 -7
- package/platforms/claude/settings.template.json +29 -28
- package/rules/common/beads-hygiene.md +3 -9
- package/rules/common/code-review.md +3 -6
- package/rules/common/coding-style.md +3 -6
- package/rules/common/comments.md +3 -7
- package/rules/common/commit-approval.md +3 -6
- package/rules/common/cx-agent-routing.md +3 -7
- package/rules/common/cx-skill-routing.md +3 -3
- package/rules/common/doc-ownership.md +3 -8
- package/rules/common/efficiency.md +3 -8
- package/rules/common/framing.md +3 -8
- package/rules/common/git-workflow.md +3 -5
- package/rules/common/no-fabrication.md +4 -12
- package/rules/common/patterns.md +3 -5
- package/rules/common/release-gates.md +3 -8
- package/rules/common/research.md +3 -8
- package/rules/common/review-before-change.md +3 -9
- package/rules/common/security.md +3 -6
- package/rules/common/skill-composition.md +3 -7
- package/rules/common/testing.md +3 -6
- package/rules/golang/coding-style.md +1 -5
- package/rules/golang/hooks.md +1 -5
- package/rules/golang/patterns.md +1 -5
- package/rules/golang/security.md +1 -5
- package/rules/golang/testing.md +1 -5
- package/rules/python/coding-style.md +1 -5
- package/rules/python/hooks.md +1 -5
- package/rules/python/patterns.md +1 -5
- package/rules/python/security.md +1 -5
- package/rules/python/testing.md +1 -5
- package/rules/swift/coding-style.md +1 -5
- package/rules/swift/hooks.md +1 -5
- package/rules/swift/patterns.md +1 -5
- package/rules/swift/security.md +1 -5
- package/rules/swift/testing.md +1 -5
- package/rules/typescript/coding-style.md +1 -5
- package/rules/typescript/hooks.md +1 -5
- package/rules/typescript/patterns.md +1 -5
- package/rules/typescript/security.md +1 -5
- package/rules/typescript/testing.md +1 -5
- package/rules/web/coding-style.md +3 -5
- package/rules/web/design-quality.md +3 -5
- package/rules/web/hooks.md +3 -5
- package/rules/web/patterns.md +3 -5
- package/rules/web/performance.md +3 -5
- package/rules/web/security.md +3 -5
- package/rules/web/testing.md +3 -5
- package/scripts/sync-specialists.mjs +269 -75
- package/skills/ai/agent-dev.md +4 -5
- package/skills/ai/llm-security.md +4 -5
- package/skills/ai/ml-ops.md +4 -5
- package/skills/ai/orchestration-workflow.md +4 -5
- package/skills/ai/prompt-and-eval.md +4 -5
- package/skills/ai/prompt-optimizer.md +4 -6
- package/skills/ai/rag-system.md +4 -5
- package/skills/architecture/api-design.md +4 -5
- package/skills/architecture/caching.md +4 -5
- package/skills/architecture/cloud-native.md +4 -5
- package/skills/architecture/message-queue.md +4 -5
- package/skills/architecture/security-arch.md +4 -5
- package/skills/compliance/ai-disclosure.md +4 -5
- package/skills/compliance/data-privacy.md +4 -5
- package/skills/compliance/license-audit.md +4 -5
- package/skills/compliance/regulatory-review.md +4 -5
- package/skills/development/cpp.md +4 -5
- package/skills/development/go.md +4 -5
- package/skills/development/java.md +4 -5
- package/skills/development/kotlin.md +4 -5
- package/skills/development/mobile-crossplatform.md +4 -5
- package/skills/development/python.md +4 -5
- package/skills/development/rust.md +4 -5
- package/skills/development/shell.md +4 -5
- package/skills/development/swift.md +4 -5
- package/skills/development/typescript.md +4 -5
- package/skills/devops/ci-cd.md +4 -5
- package/skills/devops/containerization.md +4 -5
- package/skills/devops/cost-optimization.md +4 -5
- package/skills/devops/data-engineering.md +4 -5
- package/skills/devops/database.md +4 -5
- package/skills/devops/dependency-management.md +4 -5
- package/skills/devops/devsecops.md +4 -5
- package/skills/devops/git-workflow.md +4 -5
- package/skills/devops/incident-response.md +4 -5
- package/skills/devops/monorepo.md +4 -5
- package/skills/devops/observability.md +4 -5
- package/skills/devops/performance.md +4 -5
- package/skills/devops/testing.md +4 -5
- package/skills/docs/adr-workflow.md +4 -7
- package/skills/docs/backlog-proposal-workflow.md +4 -3
- package/skills/docs/customer-profile-workflow.md +4 -3
- package/skills/docs/document-ingest-workflow.md +4 -3
- package/skills/docs/evidence-ingest-workflow.md +4 -3
- package/skills/docs/init-docs.md +4 -5
- package/skills/docs/init-project.md +4 -5
- package/skills/docs/prd-workflow.md +4 -7
- package/skills/docs/prfaq-workflow.md +4 -3
- package/skills/docs/product-intelligence-review.md +4 -3
- package/skills/docs/product-intelligence-workflow.md +4 -6
- package/skills/docs/product-signal-workflow.md +4 -5
- package/skills/docs/research-workflow.md +4 -5
- package/skills/docs/runbook-workflow.md +4 -5
- package/skills/docs/strategy-workflow.md +4 -5
- package/skills/exploration/dependency-graph-reading.md +4 -7
- package/skills/exploration/repo-map.md +4 -5
- package/skills/exploration/tracer-bullet-method.md +4 -7
- package/skills/exploration/unknown-codebase-onboarding.md +4 -7
- package/skills/frameworks/django.md +4 -5
- package/skills/frameworks/nextjs.md +4 -5
- package/skills/frameworks/react.md +4 -5
- package/skills/frameworks/spring-boot.md +4 -5
- package/skills/frontend-design/accessibility.md +4 -5
- package/skills/frontend-design/component-patterns.md +4 -5
- package/skills/frontend-design/engineering.md +4 -5
- package/skills/frontend-design/state-management.md +4 -5
- package/skills/frontend-design/ui-aesthetics.md +4 -5
- package/skills/frontend-design/ux-principles.md +4 -5
- package/skills/operating/change-management.md +4 -8
- package/skills/operating/incident-response.md +4 -8
- package/skills/operating/oncall-rotation.md +4 -7
- package/skills/operating/orchestration-reference.md +4 -10
- package/skills/quality-gates/review-work.md +4 -5
- package/skills/quality-gates/verify-change.md +4 -5
- package/skills/quality-gates/verify-module.md +4 -5
- package/skills/quality-gates/verify-quality.md +4 -5
- package/skills/quality-gates/verify-security.md +4 -5
- package/skills/roles/architect.ai-systems.md +6 -9
- package/skills/roles/architect.data.md +6 -9
- package/skills/roles/architect.enterprise.md +6 -9
- package/skills/roles/architect.integration.md +6 -9
- package/skills/roles/architect.md +7 -14
- package/skills/roles/architect.platform.md +6 -9
- package/skills/roles/data-analyst.experiment.md +6 -9
- package/skills/roles/data-analyst.md +6 -9
- package/skills/roles/data-analyst.product-intelligence.md +7 -9
- package/skills/roles/data-analyst.product.md +6 -9
- package/skills/roles/data-analyst.telemetry.md +7 -9
- package/skills/roles/data-engineer.pipeline.md +6 -9
- package/skills/roles/data-engineer.vector-retrieval.md +7 -9
- package/skills/roles/data-engineer.warehouse.md +6 -9
- package/skills/roles/debugger.md +6 -9
- package/skills/roles/designer.accessibility.md +6 -9
- package/skills/roles/designer.md +7 -9
- package/skills/roles/engineer.ai.md +6 -9
- package/skills/roles/engineer.data.md +6 -9
- package/skills/roles/engineer.md +9 -9
- package/skills/roles/engineer.platform.md +6 -9
- package/skills/roles/operator.docs.md +6 -9
- package/skills/roles/operator.md +9 -9
- package/skills/roles/operator.release.md +6 -9
- package/skills/roles/operator.sre.md +6 -9
- package/skills/roles/orchestrator.md +6 -9
- package/skills/roles/product-manager.ai-product.md +6 -9
- package/skills/roles/product-manager.business-strategy.md +6 -9
- package/skills/roles/product-manager.enterprise.md +6 -9
- package/skills/roles/product-manager.growth.md +7 -9
- package/skills/roles/product-manager.md +7 -9
- package/skills/roles/product-manager.platform.md +6 -9
- package/skills/roles/product-manager.product.md +6 -9
- package/skills/roles/qa.ai-eval.md +8 -9
- package/skills/roles/qa.api-contract.md +7 -9
- package/skills/roles/qa.data-pipeline.md +7 -9
- package/skills/roles/qa.md +7 -9
- package/skills/roles/qa.test-automation.md +6 -9
- package/skills/roles/qa.web-ui.md +7 -9
- package/skills/roles/researcher.explorer.md +6 -9
- package/skills/roles/researcher.md +8 -9
- package/skills/roles/researcher.ux.md +6 -9
- package/skills/roles/reviewer.devil-advocate.md +6 -9
- package/skills/roles/reviewer.evaluator.md +6 -9
- package/skills/roles/reviewer.md +9 -9
- package/skills/roles/reviewer.trace.md +6 -9
- package/skills/roles/security.ai.md +7 -9
- package/skills/roles/security.appsec.md +6 -9
- package/skills/roles/security.cloud.md +6 -9
- package/skills/roles/security.legal-compliance.md +6 -9
- package/skills/roles/security.md +7 -9
- package/skills/roles/security.privacy.md +7 -9
- package/skills/roles/security.supply-chain.md +7 -9
- package/skills/security/blue-team.md +4 -5
- package/skills/security/code-audit.md +4 -5
- package/skills/security/pentest.md +4 -5
- package/skills/security/red-team.md +4 -5
- package/skills/security/threat-intel.md +4 -5
- package/skills/security/vuln-research.md +4 -5
- package/skills/strategy/competitive-landscape.md +4 -8
- package/skills/strategy/market-research-methods.md +4 -8
- package/skills/strategy/narrative-arc.md +4 -8
- package/skills/strategy/pricing-positioning.md +4 -8
- package/skills/utility/clean-code.md +4 -5
- package/specialists/policy-inventory.json +14 -0
- package/specialists/registry.json +158 -13
- package/lib/hooks/env-check.mjs +0 -83
- package/lib/hooks/read-tracker.mjs +0 -61
- package/lib/policy/unified-gates.mjs +0 -96
- package/lib/server/static/assets/index-ab25c707.js +0 -70
- package/lib/server/static/assets/index-f0c80a2b.css +0 -1
- package/lib/specialist-contracts-enforce.mjs +0 -158
- package/rules/common/agents.md +0 -28
- package/rules/common/development-workflow.md +0 -32
- package/rules/common/performance.md +0 -55
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.page-title{font-size:1.5rem;font-weight:700;margin-bottom:1.5rem;color:var(--text)}.btn-secondary{background:var(--bg-muted);color:var(--text);padding:.5rem 1rem;border-radius:4px;transition:background-color .15s ease}.btn-secondary:hover{background:var(--border)}.loading,.empty{text-align:center;padding:2.5rem 0;color:var(--text-dim)}@media (max-width: 640px){aside{display:none}main{padding:1rem}}*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.card{background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:1.25rem;transition:border-color .15s ease,box-shadow .15s ease}.card:hover{border-color:transparent;box-shadow:0 0 0 1px transparent,0 10px 30px -12px #00d4ff2e,0 2px 8px -4px #b76eff1f;background-image:linear-gradient(var(--surface),var(--surface)),var(--aurora-gradient);background-origin:border-box;background-clip:padding-box,border-box}.btn{display:inline-flex;align-items:center;gap:.5rem;padding:.5rem .9rem;border-radius:8px;border:1px solid var(--border);background:var(--surface);color:var(--text);font-size:.875rem;font-weight:500;cursor:pointer;transition:border-color .15s ease,background .15s ease}.btn:hover{border-color:transparent;background-image:linear-gradient(var(--surface),var(--surface)),var(--aurora-gradient);background-origin:border-box;background-clip:padding-box,border-box}.btn-primary{background-image:linear-gradient(var(--surface),var(--surface)),var(--aurora-gradient);background-origin:border-box;background-clip:padding-box,border-box;border-color:transparent;color:var(--text)}.pip{display:inline-flex;align-items:center;gap:.5rem;padding:.125rem .5rem;font-size:.75rem;font-weight:500;border-radius:999px;border:1px solid var(--border)}.pip:before{content:"";width:.5rem;height:.5rem;border-radius:999px;background:currentColor}.pip-healthy{color:var(--status-healthy)}.pip-degraded{color:var(--status-degraded)}.pip-down{color:var(--status-down)}.hairline-aurora{height:1px;width:100%;background:var(--aurora-gradient);opacity:.45}.text-aurora{background:var(--aurora-gradient);-webkit-background-clip:text;background-clip:text;color:transparent;font-weight:600;letter-spacing:-.01em}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.visible{visibility:visible}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.inset-y-0{top:0;bottom:0}.left-0{left:0}.top-0{top:0}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.mx-1{margin-left:.25rem;margin-right:.25rem}.mb-0\.5{margin-bottom:.125rem}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mr-1\.5{margin-right:.375rem}.mr-2{margin-right:.5rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-1\.5{margin-top:.375rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-1\.5{height:.375rem}.h-16{height:4rem}.h-2{height:.5rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-32{height:8rem}.h-4{height:1rem}.h-\[55vh\]{height:55vh}.h-full{height:100%}.max-h-64{max-height:16rem}.max-h-96{max-height:24rem}.max-h-\[60vh\]{max-height:60vh}.max-h-\[80vh\]{max-height:80vh}.min-h-0{min-height:0px}.min-h-screen{min-height:100vh}.w-1\.5{width:.375rem}.w-14{width:3.5rem}.w-2{width:.5rem}.w-24{width:6rem}.w-28{width:7rem}.w-3\.5{width:.875rem}.w-32{width:8rem}.w-52{width:13rem}.w-56{width:14rem}.w-72{width:18rem}.w-8{width:2rem}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.min-w-0{min-width:0px}.min-w-\[200px\]{min-width:200px}.min-w-\[560px\]{min-width:560px}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}.max-w-5xl{max-width:64rem}.max-w-6xl{max-width:72rem}.max-w-7xl{max-width:80rem}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.-translate-x-full{--tw-translate-x: -100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-0{--tw-translate-x: 0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.cursor-help{cursor:help}.cursor-pointer{cursor:pointer}.resize-none{resize:none}.list-inside{list-style-position:inside}.list-disc{list-style-type:disc}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-\[80px_1fr\]{grid-template-columns:80px 1fr}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-baseline{align-items:baseline}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.gap-x-2{-moz-column-gap:.5rem;column-gap:.5rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.gap-y-0\.5{row-gap:.125rem}.gap-y-1{row-gap:.25rem}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.125rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem * var(--tw-space-y-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(2rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-gray-100>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(243 244 246 / var(--tw-divide-opacity, 1))}.divide-gray-50>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(249 250 251 / var(--tw-divide-opacity, 1))}.self-start{align-self:flex-start}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-l-2{border-left-width:2px}.border-r{border-right-width:1px}.border-r-2{border-right-width:2px}.border-t{border-top-width:1px}.border-amber-200{--tw-border-opacity: 1;border-color:rgb(253 230 138 / var(--tw-border-opacity, 1))}.border-amber-300{--tw-border-opacity: 1;border-color:rgb(252 211 77 / var(--tw-border-opacity, 1))}.border-amber-600{--tw-border-opacity: 1;border-color:rgb(217 119 6 / var(--tw-border-opacity, 1))}.border-aurora-cyan{border-color:var(--aurora-cyan)}.border-border{border-color:var(--border)}.border-emerald-200{--tw-border-opacity: 1;border-color:rgb(167 243 208 / var(--tw-border-opacity, 1))}.border-emerald-300{--tw-border-opacity: 1;border-color:rgb(110 231 183 / var(--tw-border-opacity, 1))}.border-gray-100{--tw-border-opacity: 1;border-color:rgb(243 244 246 / var(--tw-border-opacity, 1))}.border-gray-200{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity, 1))}.border-gray-300{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1))}.border-gray-50{--tw-border-opacity: 1;border-color:rgb(249 250 251 / var(--tw-border-opacity, 1))}.border-green-200{--tw-border-opacity: 1;border-color:rgb(187 247 208 / var(--tw-border-opacity, 1))}.border-indigo-200{--tw-border-opacity: 1;border-color:rgb(199 210 254 / var(--tw-border-opacity, 1))}.border-indigo-300{--tw-border-opacity: 1;border-color:rgb(165 180 252 / var(--tw-border-opacity, 1))}.border-indigo-500{--tw-border-opacity: 1;border-color:rgb(99 102 241 / var(--tw-border-opacity, 1))}.border-indigo-600{--tw-border-opacity: 1;border-color:rgb(79 70 229 / var(--tw-border-opacity, 1))}.border-red-200{--tw-border-opacity: 1;border-color:rgb(254 202 202 / var(--tw-border-opacity, 1))}.border-red-300{--tw-border-opacity: 1;border-color:rgb(252 165 165 / var(--tw-border-opacity, 1))}.bg-amber-100{--tw-bg-opacity: 1;background-color:rgb(254 243 199 / var(--tw-bg-opacity, 1))}.bg-amber-50{--tw-bg-opacity: 1;background-color:rgb(255 251 235 / var(--tw-bg-opacity, 1))}.bg-amber-50\/40{background-color:#fffbeb66}.bg-amber-600{--tw-bg-opacity: 1;background-color:rgb(217 119 6 / var(--tw-bg-opacity, 1))}.bg-bg{background-color:var(--bg)}.bg-bg-muted{background-color:var(--bg-muted)}.bg-black\/40{background-color:#0006}.bg-black\/50{background-color:#00000080}.bg-blue-100{--tw-bg-opacity: 1;background-color:rgb(219 234 254 / var(--tw-bg-opacity, 1))}.bg-blue-500{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity, 1))}.bg-emerald-50{--tw-bg-opacity: 1;background-color:rgb(236 253 245 / var(--tw-bg-opacity, 1))}.bg-emerald-50\/40{background-color:#ecfdf566}.bg-emerald-50\/60{background-color:#ecfdf599}.bg-emerald-500{--tw-bg-opacity: 1;background-color:rgb(16 185 129 / var(--tw-bg-opacity, 1))}.bg-gray-100{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.bg-gray-200{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.bg-gray-300{--tw-bg-opacity: 1;background-color:rgb(209 213 219 / var(--tw-bg-opacity, 1))}.bg-gray-400{--tw-bg-opacity: 1;background-color:rgb(156 163 175 / var(--tw-bg-opacity, 1))}.bg-gray-50{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.bg-gray-900{--tw-bg-opacity: 1;background-color:rgb(17 24 39 / var(--tw-bg-opacity, 1))}.bg-green-100{--tw-bg-opacity: 1;background-color:rgb(220 252 231 / var(--tw-bg-opacity, 1))}.bg-green-50{--tw-bg-opacity: 1;background-color:rgb(240 253 244 / var(--tw-bg-opacity, 1))}.bg-green-500{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))}.bg-indigo-50{--tw-bg-opacity: 1;background-color:rgb(238 242 255 / var(--tw-bg-opacity, 1))}.bg-indigo-50\/50{background-color:#eef2ff80}.bg-indigo-600{--tw-bg-opacity: 1;background-color:rgb(79 70 229 / var(--tw-bg-opacity, 1))}.bg-orange-100{--tw-bg-opacity: 1;background-color:rgb(255 237 213 / var(--tw-bg-opacity, 1))}.bg-red-100{--tw-bg-opacity: 1;background-color:rgb(254 226 226 / var(--tw-bg-opacity, 1))}.bg-red-50{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.bg-red-500{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity, 1))}.bg-surface{background-color:var(--surface)}.bg-violet-50{--tw-bg-opacity: 1;background-color:rgb(245 243 255 / var(--tw-bg-opacity, 1))}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-yellow-100{--tw-bg-opacity: 1;background-color:rgb(254 249 195 / var(--tw-bg-opacity, 1))}.bg-yellow-500{--tw-bg-opacity: 1;background-color:rgb(234 179 8 / var(--tw-bg-opacity, 1))}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.from-indigo-50{--tw-gradient-from: #eef2ff var(--tw-gradient-from-position);--tw-gradient-to: rgb(238 242 255 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-indigo-600{--tw-gradient-from: #4f46e5 var(--tw-gradient-from-position);--tw-gradient-to: rgb(79 70 229 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.to-violet-50{--tw-gradient-to: #f5f3ff var(--tw-gradient-to-position)}.to-violet-600{--tw-gradient-to: #7c3aed var(--tw-gradient-to-position)}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-20{padding-top:5rem;padding-bottom:5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.pb-2{padding-bottom:.5rem}.pb-3{padding-bottom:.75rem}.pl-3{padding-left:.75rem}.pr-3{padding-right:.75rem}.pr-4{padding-right:1rem}.pt-1{padding-top:.25rem}.pt-2{padding-top:.5rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-top{vertical-align:top}.align-middle{vertical-align:middle}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.font-sans{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.capitalize{text-transform:capitalize}.normal-case{text-transform:none}.italic{font-style:italic}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.tracking-tight{letter-spacing:-.025em}.tracking-wide{letter-spacing:.025em}.tracking-wider{letter-spacing:.05em}.text-amber-700{--tw-text-opacity: 1;color:rgb(180 83 9 / var(--tw-text-opacity, 1))}.text-amber-800{--tw-text-opacity: 1;color:rgb(146 64 14 / var(--tw-text-opacity, 1))}.text-amber-900{--tw-text-opacity: 1;color:rgb(120 53 15 / var(--tw-text-opacity, 1))}.text-blue-700{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.text-blue-800{--tw-text-opacity: 1;color:rgb(30 64 175 / var(--tw-text-opacity, 1))}.text-cyan-700{--tw-text-opacity: 1;color:rgb(14 116 144 / var(--tw-text-opacity, 1))}.text-emerald-700{--tw-text-opacity: 1;color:rgb(4 120 87 / var(--tw-text-opacity, 1))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-gray-600{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.text-gray-700{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.text-gray-800{--tw-text-opacity: 1;color:rgb(31 41 55 / var(--tw-text-opacity, 1))}.text-gray-900{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.text-green-400{--tw-text-opacity: 1;color:rgb(74 222 128 / var(--tw-text-opacity, 1))}.text-green-600{--tw-text-opacity: 1;color:rgb(22 163 74 / var(--tw-text-opacity, 1))}.text-green-700{--tw-text-opacity: 1;color:rgb(21 128 61 / var(--tw-text-opacity, 1))}.text-green-800{--tw-text-opacity: 1;color:rgb(22 101 52 / var(--tw-text-opacity, 1))}.text-green-900{--tw-text-opacity: 1;color:rgb(20 83 45 / var(--tw-text-opacity, 1))}.text-indigo-600{--tw-text-opacity: 1;color:rgb(79 70 229 / var(--tw-text-opacity, 1))}.text-indigo-700{--tw-text-opacity: 1;color:rgb(67 56 202 / var(--tw-text-opacity, 1))}.text-indigo-900{--tw-text-opacity: 1;color:rgb(49 46 129 / var(--tw-text-opacity, 1))}.text-orange-800{--tw-text-opacity: 1;color:rgb(154 52 18 / var(--tw-text-opacity, 1))}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.text-red-700{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity, 1))}.text-red-800{--tw-text-opacity: 1;color:rgb(153 27 27 / var(--tw-text-opacity, 1))}.text-text{color:var(--text)}.text-text-dim{color:var(--text-dim)}.text-text-muted{color:var(--text-muted)}.text-violet-800{--tw-text-opacity: 1;color:rgb(91 33 182 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-yellow-600{--tw-text-opacity: 1;color:rgb(202 138 4 / var(--tw-text-opacity, 1))}.text-yellow-800{--tw-text-opacity: 1;color:rgb(133 77 14 / var(--tw-text-opacity, 1))}.underline{text-decoration-line:underline}.line-through{text-decoration-line:line-through}.decoration-text-dim{text-decoration-color:var(--text-dim)}.decoration-dotted{text-decoration-style:dotted}.underline-offset-2{text-underline-offset:2px}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.ring-1{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-indigo-100{--tw-ring-opacity: 1;--tw-ring-color: rgb(224 231 255 / var(--tw-ring-opacity, 1))}.\!filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)!important}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-150{transition-duration:.15s}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}:root{--ink-50: #ffffff;--ink-100: #f5f5f5;--ink-200: #e6e6e6;--ink-300: #cccccc;--ink-400: #a3a3a3;--ink-500: #737373;--ink-600: #525252;--ink-700: #2c2c2c;--ink-800: #1a1a1a;--ink-900: #000000;--aurora-mint: #00ffaa;--aurora-cyan: #00d4ff;--aurora-violet: #b76eff;--aurora-pink: #ff66c4;--aurora-gradient: linear-gradient( 135deg, var(--aurora-mint) 0%, var(--aurora-cyan) 35%, var(--aurora-violet) 70%, var(--aurora-pink) 100% );--bg: var(--ink-50);--bg-muted: var(--ink-100);--surface: var(--ink-50);--border: var(--ink-200);--text: var(--ink-900);--text-muted: var(--ink-600);--text-dim: var(--ink-500);--status-healthy: #16a34a;--status-degraded: #d97706;--status-down: #dc2626;--focus-ring: var(--aurora-cyan);color-scheme:light dark}@media (prefers-color-scheme: dark){:root{--bg: var(--ink-900);--bg-muted: var(--ink-800);--surface: var(--ink-900);--border: var(--ink-700);--text: var(--ink-50);--text-muted: var(--ink-300);--text-dim: var(--ink-400);--status-healthy: #4ade80;--status-degraded: #fbbf24;--status-down: #f87171}}[data-theme=light]{--bg: var(--ink-50);--bg-muted: var(--ink-100);--surface: var(--ink-50);--border: var(--ink-200);--text: var(--ink-900);--text-muted: var(--ink-600);--text-dim: var(--ink-500)}[data-theme=dark]{--bg: var(--ink-900);--bg-muted: var(--ink-800);--surface: var(--ink-900);--border: var(--ink-700);--text: var(--ink-50);--text-muted: var(--ink-300);--text-dim: var(--ink-400)}html,body,#root{background:var(--bg);color:var(--text);min-height:100vh}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif}body:before{content:"";position:fixed;top:0;right:0;bottom:0;left:0;pointer-events:none;z-index:0;background:radial-gradient(80vmax 60vmax at 12% 6%,rgba(0,212,255,.07),transparent 60%),radial-gradient(60vmax 50vmax at 92% 18%,rgba(183,110,255,.06),transparent 60%),radial-gradient(70vmax 55vmax at 50% 110%,rgba(0,255,170,.05),transparent 65%)}#root{position:relative;z-index:1}@media (prefers-reduced-motion: reduce){*,*:before,*:after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important;scroll-behavior:auto!important}}:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px;border-radius:4px}@media (prefers-color-scheme: dark){:root:not([data-theme=light]){--legacy-gray-50: rgba(255,255,255,.04);--legacy-gray-100: rgba(255,255,255,.07);--legacy-gray-200: rgba(255,255,255,.1);--legacy-gray-300: rgba(255,255,255,.14);--legacy-gray-400: rgba(255,255,255,.45);--legacy-gray-500: rgba(255,255,255,.6);--legacy-gray-600: rgba(255,255,255,.72);--legacy-gray-700: rgba(255,255,255,.84);--legacy-gray-800: rgba(255,255,255,.92);--legacy-gray-900: var(--ink-50)}}[data-theme=dark]{--legacy-gray-50: rgba(255,255,255,.04);--legacy-gray-100: rgba(255,255,255,.07);--legacy-gray-200: rgba(255,255,255,.1);--legacy-gray-300: rgba(255,255,255,.14);--legacy-gray-400: rgba(255,255,255,.45);--legacy-gray-500: rgba(255,255,255,.6);--legacy-gray-600: rgba(255,255,255,.72);--legacy-gray-700: rgba(255,255,255,.84);--legacy-gray-800: rgba(255,255,255,.92);--legacy-gray-900: var(--ink-50)}@media (prefers-color-scheme: dark){:root:not([data-theme=light]) .bg-white{background-color:var(--surface)!important}:root:not([data-theme=light]) .bg-gray-50{background-color:var(--legacy-gray-50)!important}:root:not([data-theme=light]) .bg-gray-100,:root:not([data-theme=light]) .hover\:bg-gray-100:hover{background-color:var(--legacy-gray-100)!important}:root:not([data-theme=light]) .bg-gray-200,:root:not([data-theme=light]) .hover\:bg-gray-200:hover{background-color:var(--legacy-gray-200)!important}:root:not([data-theme=light]) .bg-gray-900{background-color:var(--ink-900)!important}:root:not([data-theme=light]) .border-gray-100,:root:not([data-theme=light]) .border-gray-200,:root:not([data-theme=light]) .border-gray-300{border-color:var(--border)!important}:root:not([data-theme=light]) .text-gray-500{color:var(--legacy-gray-500)!important}:root:not([data-theme=light]) .text-gray-600{color:var(--legacy-gray-600)!important}:root:not([data-theme=light]) .text-gray-700{color:var(--legacy-gray-700)!important}:root:not([data-theme=light]) .text-gray-800{color:var(--legacy-gray-800)!important}:root:not([data-theme=light]) .text-gray-900{color:var(--legacy-gray-900)!important}:root:not([data-theme=light]) .bg-red-100{background-color:#ef44442e!important}:root:not([data-theme=light]) .bg-red-50{background-color:#ef44441a!important}:root:not([data-theme=light]) .text-red-700,:root:not([data-theme=light]) .text-red-800{color:#f87171!important}:root:not([data-theme=light]) .text-red-500{color:#fca5a5!important}:root:not([data-theme=light]) .bg-orange-100{background-color:#fb923c2e!important}:root:not([data-theme=light]) .text-orange-800{color:#fdba74!important}:root:not([data-theme=light]) .bg-yellow-100{background-color:#eab3082e!important}:root:not([data-theme=light]) .text-yellow-800{color:#fde047!important}:root:not([data-theme=light]) .text-yellow-900{color:#facc15!important}:root:not([data-theme=light]) .bg-blue-100{background-color:#3b82f62e!important}:root:not([data-theme=light]) .text-blue-800,:root:not([data-theme=light]) .text-blue-700{color:#93c5fd!important}:root:not([data-theme=light]) .bg-green-100{background-color:#22c55e2e!important}:root:not([data-theme=light]) .text-green-800,:root:not([data-theme=light]) .text-green-700{color:#86efac!important}:root:not([data-theme=light]) .text-green-600{color:#6ee7b7!important}:root:not([data-theme=light]) .text-green-400{color:#4ade80!important}:root:not([data-theme=light]) .bg-violet-100,:root:not([data-theme=light]) .bg-violet-50{background-color:#a78bfa2e!important}:root:not([data-theme=light]) .text-violet-800{color:#c4b5fd!important}:root:not([data-theme=light]) .bg-indigo-50\/50,:root:not([data-theme=light]) .bg-indigo-50{background-color:#6366f126!important}:root:not([data-theme=light]) .text-indigo-600,:root:not([data-theme=light]) .text-indigo-700{color:#a5b4fc!important}:root:not([data-theme=light]) .bg-amber-50{background-color:#f59e0b1a!important}:root:not([data-theme=light]) .text-amber-800{color:#fcd34d!important}}[data-theme=dark] .bg-white{background-color:var(--surface)!important}[data-theme=dark] .bg-gray-50{background-color:var(--legacy-gray-50)!important}[data-theme=dark] .bg-gray-100,[data-theme=dark] .hover\:bg-gray-100:hover{background-color:var(--legacy-gray-100)!important}[data-theme=dark] .bg-gray-200,[data-theme=dark] .hover\:bg-gray-200:hover{background-color:var(--legacy-gray-200)!important}[data-theme=dark] .bg-gray-900{background-color:var(--ink-900)!important}[data-theme=dark] .border-gray-100,[data-theme=dark] .border-gray-200,[data-theme=dark] .border-gray-300{border-color:var(--border)!important}[data-theme=dark] .text-gray-500{color:var(--legacy-gray-500)!important}[data-theme=dark] .text-gray-600{color:var(--legacy-gray-600)!important}[data-theme=dark] .text-gray-700{color:var(--legacy-gray-700)!important}[data-theme=dark] .text-gray-800{color:var(--legacy-gray-800)!important}[data-theme=dark] .text-gray-900{color:var(--legacy-gray-900)!important}[data-theme=dark] .bg-red-100{background-color:#ef44442e!important}[data-theme=dark] .bg-red-50{background-color:#ef44441a!important}[data-theme=dark] .text-red-700,[data-theme=dark] .text-red-800{color:#f87171!important}[data-theme=dark] .text-red-500{color:#fca5a5!important}[data-theme=dark] .bg-orange-100{background-color:#fb923c2e!important}[data-theme=dark] .text-orange-800{color:#fdba74!important}[data-theme=dark] .bg-yellow-100{background-color:#eab3082e!important}[data-theme=dark] .text-yellow-800{color:#fde047!important}[data-theme=dark] .text-yellow-900{color:#facc15!important}[data-theme=dark] .bg-blue-100{background-color:#3b82f62e!important}[data-theme=dark] .text-blue-800,[data-theme=dark] .text-blue-700{color:#93c5fd!important}[data-theme=dark] .bg-green-100{background-color:#22c55e2e!important}[data-theme=dark] .text-green-800,[data-theme=dark] .text-green-700{color:#86efac!important}[data-theme=dark] .text-green-600{color:#6ee7b7!important}[data-theme=dark] .text-green-400{color:#4ade80!important}[data-theme=dark] .bg-violet-100,[data-theme=dark] .bg-violet-50{background-color:#a78bfa2e!important}[data-theme=dark] .text-violet-800{color:#c4b5fd!important}[data-theme=dark] .bg-indigo-50\/50,[data-theme=dark] .bg-indigo-50{background-color:#6366f126!important}[data-theme=dark] .text-indigo-600,[data-theme=dark] .text-indigo-700{color:#a5b4fc!important}[data-theme=dark] .bg-amber-50{background-color:#f59e0b1a!important}[data-theme=dark] .text-amber-800{color:#fcd34d!important}.hover\:bg-amber-700:hover{--tw-bg-opacity: 1;background-color:rgb(180 83 9 / var(--tw-bg-opacity, 1))}.hover\:bg-bg-muted:hover{background-color:var(--bg-muted)}.hover\:bg-gray-100:hover{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-200:hover{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-50:hover{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-800:hover{--tw-bg-opacity: 1;background-color:rgb(31 41 55 / var(--tw-bg-opacity, 1))}.hover\:bg-indigo-50:hover{--tw-bg-opacity: 1;background-color:rgb(238 242 255 / var(--tw-bg-opacity, 1))}.hover\:bg-indigo-700:hover{--tw-bg-opacity: 1;background-color:rgb(67 56 202 / var(--tw-bg-opacity, 1))}.hover\:bg-red-50:hover{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.hover\:from-indigo-700:hover{--tw-gradient-from: #4338ca var(--tw-gradient-from-position);--tw-gradient-to: rgb(67 56 202 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.hover\:to-violet-700:hover{--tw-gradient-to: #6d28d9 var(--tw-gradient-to-position)}.hover\:text-gray-700:hover{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.hover\:text-indigo-900:hover{--tw-text-opacity: 1;color:rgb(49 46 129 / var(--tw-text-opacity, 1))}.hover\:text-red-900:hover{--tw-text-opacity: 1;color:rgb(127 29 29 / var(--tw-text-opacity, 1))}.hover\:text-text:hover{color:var(--text)}.hover\:no-underline:hover{text-decoration-line:none}.focus\:not-sr-only:focus{position:static;width:auto;height:auto;padding:0;margin:0;overflow:visible;clip:auto;white-space:normal}.focus\:fixed:focus{position:fixed}.focus\:left-2:focus{left:.5rem}.focus\:top-2:focus{top:.5rem}.focus\:z-50:focus{z-index:50}.focus\:rounded-md:focus{border-radius:.375rem}.focus\:border:focus{border-width:1px}.focus\:border-border:focus{border-color:var(--border)}.focus\:border-indigo-400:focus{--tw-border-opacity: 1;border-color:rgb(129 140 248 / var(--tw-border-opacity, 1))}.focus\:bg-surface:focus{background-color:var(--surface)}.focus\:px-3:focus{padding-left:.75rem;padding-right:.75rem}.focus\:py-2:focus{padding-top:.5rem;padding-bottom:.5rem}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:bg-gray-100:disabled{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}@media (min-width: 640px){.sm\:hidden{display:none}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:p-6{padding:1.5rem}.sm\:text-3xl{font-size:1.875rem;line-height:2.25rem}}@media (min-width: 768px){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}}@media (min-width: 1024px){.lg\:relative{position:relative}.lg\:col-span-2{grid-column:span 2 / span 2}.lg\:block{display:block}.lg\:hidden{display:none}.lg\:w-64{width:16rem}.lg\:translate-x-0{--tw-translate-x: 0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.lg\:grid-cols-7{grid-template-columns:repeat(7,minmax(0,1fr))}.lg\:grid-cols-\[260px_1fr\]{grid-template-columns:260px 1fr}.lg\:flex-row{flex-direction:row}.lg\:p-8{padding:2rem}}
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* lib/specialist-contracts-enforce.mjs — runtime contract enforcement.
|
|
3
|
-
*
|
|
4
|
-
* Wraps `validatePacket` from `lib/specialist-contracts.mjs` with three production
|
|
5
|
-
* concerns:
|
|
6
|
-
*
|
|
7
|
-
* 1. Block on violation. `enforcePacket` throws a `ContractViolationError`
|
|
8
|
-
* when the packet doesn't satisfy the contract direction. Callers can
|
|
9
|
-
* catch and degrade if they want advisory mode, but the default is hard
|
|
10
|
-
* enforcement so contract bugs surface loudly.
|
|
11
|
-
*
|
|
12
|
-
* 2. Tamper-evident violation log. Every violation appends a JSONL record
|
|
13
|
-
* to `~/.cx/contract-violations.jsonl` with a sha256 chain-hash over
|
|
14
|
-
* the prior line. Same pattern as the mutation audit trail. Operators
|
|
15
|
-
* can replay the chain to detect after-the-fact tampering.
|
|
16
|
-
*
|
|
17
|
-
* 3. Visibility into `construct doctor`. `recentViolations(windowMs)`
|
|
18
|
-
* returns the last N violations so doctor can surface
|
|
19
|
-
* "3 contract violations in the last 24h — see ~/.cx/contract-violations.jsonl".
|
|
20
|
-
*
|
|
21
|
-
* The enforcement is identity-aware. Each violation logs the active agent
|
|
22
|
-
* (via `~/.cx/last-agent.json` like audit-trail does) so operators can
|
|
23
|
-
* identify which producer or consumer is at fault.
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
import { existsSync, mkdirSync, statSync, readFileSync, appendFileSync } from 'node:fs';
|
|
27
|
-
import { join } from 'node:path';
|
|
28
|
-
import { homedir } from 'node:os';
|
|
29
|
-
import { createHash } from 'node:crypto';
|
|
30
|
-
import { getContractById, validatePacket } from './specialist-contracts.mjs';
|
|
31
|
-
import { validatePostconditions } from './specialists/postconditions.mjs';
|
|
32
|
-
|
|
33
|
-
const CX_DIR = join(homedir(), '.cx');
|
|
34
|
-
const LOG_FILE = join(CX_DIR, 'contract-violations.jsonl');
|
|
35
|
-
const LAST_AGENT = join(CX_DIR, 'last-agent.json');
|
|
36
|
-
|
|
37
|
-
export class ContractViolationError extends Error {
|
|
38
|
-
constructor({ contractId, direction, missing, verdict = 'CONTRACT_VIOLATION', postconditionFailures = [] }) {
|
|
39
|
-
const detail = postconditionFailures.length > 0
|
|
40
|
-
? `postcondition(s) failed: ${postconditionFailures.map((f) => f.id).join(', ')}`
|
|
41
|
-
: `missing field(s): ${(missing || []).join(', ')}`;
|
|
42
|
-
super(`contract '${contractId}' (${direction}) violated — ${detail}`);
|
|
43
|
-
this.name = 'ContractViolationError';
|
|
44
|
-
this.contractId = contractId;
|
|
45
|
-
this.direction = direction;
|
|
46
|
-
this.missing = missing || [];
|
|
47
|
-
this.verdict = verdict;
|
|
48
|
-
this.postconditionFailures = postconditionFailures;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function sha256(input) { return createHash('sha256').update(input).digest('hex'); }
|
|
53
|
-
|
|
54
|
-
function readLastAgent() {
|
|
55
|
-
try { return JSON.parse(readFileSync(LAST_AGENT, 'utf8'))?.agent || 'construct'; }
|
|
56
|
-
catch { return 'construct'; }
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function readPrevLineHash() {
|
|
60
|
-
try {
|
|
61
|
-
if (!existsSync(LOG_FILE)) return null;
|
|
62
|
-
const size = statSync(LOG_FILE).size;
|
|
63
|
-
if (size === 0) return null;
|
|
64
|
-
const tail = readFileSync(LOG_FILE, 'utf8').slice(Math.max(0, size - 2048));
|
|
65
|
-
const lines = tail.split('\n').filter(Boolean);
|
|
66
|
-
return lines.length === 0 ? null : sha256(lines[lines.length - 1]);
|
|
67
|
-
} catch { return null; }
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function logViolation(contractId, direction, missing, packet, extra = {}) {
|
|
71
|
-
try {
|
|
72
|
-
mkdirSync(CX_DIR, { recursive: true });
|
|
73
|
-
const record = {
|
|
74
|
-
ts: new Date().toISOString(),
|
|
75
|
-
agent: readLastAgent(),
|
|
76
|
-
contractId,
|
|
77
|
-
direction,
|
|
78
|
-
missing,
|
|
79
|
-
packet_keys: packet && typeof packet === 'object' ? Object.keys(packet) : null,
|
|
80
|
-
prev_line_hash: readPrevLineHash(),
|
|
81
|
-
...extra,
|
|
82
|
-
};
|
|
83
|
-
appendFileSync(LOG_FILE, JSON.stringify(record) + '\n', 'utf8');
|
|
84
|
-
} catch { /* logging is best-effort */ }
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Validate `packet` against `contractId` in the given `direction`. Throws
|
|
89
|
-
* a `ContractViolationError` on failure (and logs the violation). Returns
|
|
90
|
-
* the validation result on success so callers can inspect the resolved
|
|
91
|
-
* contract metadata.
|
|
92
|
-
*
|
|
93
|
-
* For `direction === 'output'`, also evaluates the producer's binary
|
|
94
|
-
* postconditions from `lib/agents/postconditions.mjs`. A failed postcondition
|
|
95
|
-
* raises with `verdict: 'BLOCKED_CONTRACT'` so the dispatcher can branch on
|
|
96
|
-
* the typed verdict rather than parsing the error message.
|
|
97
|
-
*
|
|
98
|
-
* @param {string} contractId
|
|
99
|
-
* @param {object} packet
|
|
100
|
-
* @param {'input'|'output'} [direction]
|
|
101
|
-
* @returns {{ ok: true, contract, direction }}
|
|
102
|
-
*/
|
|
103
|
-
export function enforcePacket(contractId, packet, direction = 'input') {
|
|
104
|
-
const result = validatePacket(contractId, packet, direction);
|
|
105
|
-
if (!result.ok) {
|
|
106
|
-
if (result.reason === 'contract-not-found') {
|
|
107
|
-
throw new ContractViolationError({
|
|
108
|
-
contractId,
|
|
109
|
-
direction,
|
|
110
|
-
missing: ['(contract not found)'],
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
logViolation(contractId, direction, result.missing || [], packet);
|
|
114
|
-
throw new ContractViolationError({
|
|
115
|
-
contractId,
|
|
116
|
-
direction,
|
|
117
|
-
missing: result.missing || [],
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (direction === 'output') {
|
|
122
|
-
const contract = result.contract || getContractById(contractId);
|
|
123
|
-
const producer = contract?.producer;
|
|
124
|
-
if (producer) {
|
|
125
|
-
const postcondition = validatePostconditions(producer, packet);
|
|
126
|
-
if (!postcondition.ok) {
|
|
127
|
-
logViolation(contractId, direction, [], packet, {
|
|
128
|
-
verdict: 'BLOCKED_CONTRACT',
|
|
129
|
-
postconditionFailures: postcondition.failures,
|
|
130
|
-
});
|
|
131
|
-
throw new ContractViolationError({
|
|
132
|
-
contractId,
|
|
133
|
-
direction,
|
|
134
|
-
verdict: 'BLOCKED_CONTRACT',
|
|
135
|
-
postconditionFailures: postcondition.failures,
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
return result;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Read recent violations from the chain log. Returns oldest-first.
|
|
146
|
-
*/
|
|
147
|
-
export function recentViolations({ windowMs = 24 * 60 * 60 * 1000 } = {}) {
|
|
148
|
-
if (!existsSync(LOG_FILE)) return [];
|
|
149
|
-
try {
|
|
150
|
-
const cutoff = Date.now() - windowMs;
|
|
151
|
-
return readFileSync(LOG_FILE, 'utf8')
|
|
152
|
-
.trim()
|
|
153
|
-
.split('\n')
|
|
154
|
-
.filter(Boolean)
|
|
155
|
-
.map((line) => { try { return JSON.parse(line); } catch { return null; } })
|
|
156
|
-
.filter((r) => r && new Date(r.ts).getTime() >= cutoff);
|
|
157
|
-
} catch { return []; }
|
|
158
|
-
}
|
package/rules/common/agents.md
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
rules/common/agents.md: platform-agnostic agent orchestration guidance.
|
|
3
|
-
|
|
4
|
-
Defines when to route to specialist agents, parallel execution rules,
|
|
5
|
-
and multi-perspective analysis patterns. Does not reference specific
|
|
6
|
-
platform agent types or config paths.
|
|
7
|
-
-->
|
|
8
|
-
# Agent Orchestration
|
|
9
|
-
|
|
10
|
-
## Immediate Agent Usage
|
|
11
|
-
|
|
12
|
-
No user prompt needed: match the task to the right specialist:
|
|
13
|
-
1. Complex feature requests - planning specialist
|
|
14
|
-
2. Code just written/modified - code review specialist
|
|
15
|
-
3. Bug fix or new feature - TDD specialist
|
|
16
|
-
4. Architectural decision - architecture specialist
|
|
17
|
-
|
|
18
|
-
## Parallel Task Execution
|
|
19
|
-
|
|
20
|
-
ALWAYS use parallel execution for independent operations. Launch multiple specialists concurrently when their work is independent.
|
|
21
|
-
|
|
22
|
-
## Multi-Perspective Analysis
|
|
23
|
-
|
|
24
|
-
For complex problems, use multiple specialist perspectives:
|
|
25
|
-
- Factual reviewer
|
|
26
|
-
- Senior engineer
|
|
27
|
-
- Security expert
|
|
28
|
-
- Consistency reviewer
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
rules/common/development-workflow.md: feature implementation pipeline.
|
|
3
|
-
|
|
4
|
-
Defines the research-plan-TDD-review-commit workflow that runs before
|
|
5
|
-
git operations. References testing.md, code-review.md, git-workflow.md.
|
|
6
|
-
-->
|
|
7
|
-
# Development Workflow
|
|
8
|
-
|
|
9
|
-
## Feature Implementation Workflow
|
|
10
|
-
|
|
11
|
-
0. **Research & Reuse** _(mandatory before any new implementation or artifact)_
|
|
12
|
-
- **Search existing code first:** Look for existing implementations, templates, and patterns before writing anything new.
|
|
13
|
-
- **Search existing artifacts:** Before authoring a doc, rule, template, strategy, PRD, ADR, or RFC, audit what already exists. See [review-before-change.md](review-before-change.md) for the audit checklist. Extend or supersede; do not duplicate.
|
|
14
|
-
- **Check docs:** Confirm API behavior, package usage, and version-specific details before implementing.
|
|
15
|
-
- **Check package registries:** npm, PyPI, crates.io before writing utility code.
|
|
16
|
-
- Prefer adopting a proven approach over writing net-new code.
|
|
17
|
-
|
|
18
|
-
1. **Plan** - Break into phases; identify dependencies and risks.
|
|
19
|
-
|
|
20
|
-
2. **TDD** - Write tests first (RED), implement (GREEN), refactor (IMPROVE). See [testing.md](testing.md).
|
|
21
|
-
|
|
22
|
-
3. **Code Review** - Review immediately after writing. See [code-review.md](code-review.md).
|
|
23
|
-
|
|
24
|
-
3.5. **Docs** _(mandatory for any user-facing change)_
|
|
25
|
-
- If you added or changed a CLI command, API endpoint, config option, or architecture boundary: update `docs/concepts/architecture.md` and create or update the relevant `docs/cookbook/` recipe.
|
|
26
|
-
- If you added a CLI command, ensure the cookbook index links to a recipe for it.
|
|
27
|
-
- Run `construct docs:update` to regenerate AUTO-managed regions.
|
|
28
|
-
- A change is not DONE if a user-facing capability exists with no documentation.
|
|
29
|
-
|
|
30
|
-
4. **Commit** - Conventional commits format. See [git-workflow.md](git-workflow.md).
|
|
31
|
-
|
|
32
|
-
5. **Pre-Review Checks** - CI passing, conflicts resolved, branch synced.
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
rules/common/performance.md: model-agnostic performance and context management rules.
|
|
3
|
-
|
|
4
|
-
Defines model selection tiers, context window management heuristics,
|
|
5
|
-
and build troubleshooting steps. No platform-specific tool names or config paths.
|
|
6
|
-
-->
|
|
7
|
-
# Performance Optimization
|
|
8
|
-
|
|
9
|
-
## Model Selection Strategy
|
|
10
|
-
|
|
11
|
-
**Fast tier** (small/cheap models):
|
|
12
|
-
- Lightweight agents with frequent invocation
|
|
13
|
-
- Pair programming and code generation
|
|
14
|
-
- Worker agents in multi-agent systems
|
|
15
|
-
|
|
16
|
-
**Standard tier** (mid-range models):
|
|
17
|
-
- Main development work
|
|
18
|
-
- Orchestrating multi-agent workflows
|
|
19
|
-
- Complex coding tasks
|
|
20
|
-
|
|
21
|
-
**Reasoning tier** (large/frontier models):
|
|
22
|
-
- Complex architectural decisions
|
|
23
|
-
- Maximum reasoning requirements
|
|
24
|
-
- Research and analysis tasks
|
|
25
|
-
|
|
26
|
-
## Context Window Management
|
|
27
|
-
|
|
28
|
-
Avoid last 20% of context window for:
|
|
29
|
-
- Large-scale refactoring
|
|
30
|
-
- Feature implementation spanning multiple files
|
|
31
|
-
- Debugging complex interactions
|
|
32
|
-
|
|
33
|
-
Prefer this retrieval ladder before loading more context:
|
|
34
|
-
1. Targeted search to narrow candidate files
|
|
35
|
-
2. Targeted reads (aim for <400 lines)
|
|
36
|
-
3. Parallel reads for the minimum necessary file set
|
|
37
|
-
4. Summarize to a context artifact before broad re-exploration
|
|
38
|
-
|
|
39
|
-
Heuristics:
|
|
40
|
-
- Re-reading the same file multiple times without a state change is a retrieval smell.
|
|
41
|
-
- Large reads should be reserved for files where local structure matters more than symbol search.
|
|
42
|
-
- Use workflow/context artifacts as cached state instead of rediscovering background repeatedly.
|
|
43
|
-
|
|
44
|
-
Lower context sensitivity tasks:
|
|
45
|
-
- Single-file edits
|
|
46
|
-
- Independent utility creation
|
|
47
|
-
- Documentation updates
|
|
48
|
-
- Simple bug fixes
|
|
49
|
-
|
|
50
|
-
## Build Troubleshooting
|
|
51
|
-
|
|
52
|
-
If build fails:
|
|
53
|
-
1. Analyze error messages
|
|
54
|
-
2. Fix incrementally
|
|
55
|
-
3. Verify after each fix
|