@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.
Files changed (337) hide show
  1. package/README.md +14 -2
  2. package/bin/construct +262 -14
  3. package/bin/construct-postinstall.mjs +23 -2
  4. package/commands/build/feature.md +0 -6
  5. package/commands/build/fix.md +0 -6
  6. package/commands/design/access.md +0 -6
  7. package/commands/design/flow.md +0 -6
  8. package/commands/design/ui.md +0 -6
  9. package/commands/measure/experiment.md +0 -6
  10. package/commands/measure/metrics.md +0 -6
  11. package/commands/measure/results.md +0 -6
  12. package/commands/plan/api.md +0 -6
  13. package/commands/plan/challenge.md +0 -6
  14. package/commands/plan/decide.md +0 -6
  15. package/commands/plan/feature.md +0 -7
  16. package/commands/plan/requirements.md +0 -6
  17. package/commands/remember/context.md +0 -6
  18. package/commands/remember/handoff.md +0 -6
  19. package/commands/remember/runbook.md +0 -6
  20. package/commands/review/code.md +0 -6
  21. package/commands/review/quality.md +0 -6
  22. package/commands/review/security.md +0 -6
  23. package/commands/ship/ready.md +0 -6
  24. package/commands/ship/release.md +0 -6
  25. package/commands/ship/status.md +0 -6
  26. package/commands/understand/docs.md +0 -6
  27. package/commands/understand/research.md +0 -6
  28. package/commands/understand/this.md +0 -6
  29. package/commands/understand/why.md +0 -6
  30. package/commands/work/clean.md +0 -6
  31. package/commands/work/drive.md +0 -6
  32. package/commands/work/optimize-prompts.md +0 -6
  33. package/commands/work/parallel-review.md +0 -6
  34. package/lib/auto-docs.mjs +11 -7
  35. package/lib/beads-client.mjs +19 -1
  36. package/lib/comment-lint.mjs +5 -1
  37. package/lib/context-state.mjs +15 -3
  38. package/lib/contracts/validate.mjs +54 -10
  39. package/lib/contracts/violation-log.mjs +154 -0
  40. package/lib/dashboard-static.mjs +7 -4
  41. package/lib/doc-stamp.mjs +16 -0
  42. package/lib/docs-verify.mjs +1 -8
  43. package/lib/doctor/watchers/bd-watch.mjs +6 -2
  44. package/lib/document-extract/docling-client.mjs +114 -0
  45. package/lib/document-extract/docling-sidecar.py +122 -0
  46. package/lib/document-extract/whisper-client.mjs +79 -0
  47. package/lib/document-extract.mjs +73 -8
  48. package/lib/document-ingest.mjs +26 -4
  49. package/lib/embed/daemon.mjs +26 -1
  50. package/lib/embed/docs-lifecycle.mjs +19 -0
  51. package/lib/embed/inbox.mjs +85 -2
  52. package/lib/embed/recommendation-store.mjs +29 -0
  53. package/lib/flavors/loader.mjs +1 -1
  54. package/lib/gates-audit.mjs +18 -12
  55. package/lib/handoffs/contract.mjs +2 -2
  56. package/lib/hooks/_lib/input.mjs +52 -0
  57. package/lib/hooks/adaptive-lint.mjs +4 -0
  58. package/lib/hooks/agent-tracker.mjs +59 -15
  59. package/lib/hooks/audit-reads.mjs +83 -42
  60. package/lib/hooks/audit-trail.mjs +28 -18
  61. package/lib/hooks/bash-output-logger.mjs +8 -2
  62. package/lib/hooks/block-no-verify.mjs +4 -0
  63. package/lib/hooks/ci-status-check.mjs +4 -0
  64. package/lib/hooks/comment-lint.mjs +6 -4
  65. package/lib/hooks/config-protection.mjs +4 -0
  66. package/lib/hooks/context-watch.mjs +4 -0
  67. package/lib/hooks/context-window-recovery.mjs +4 -0
  68. package/lib/hooks/dep-audit.mjs +12 -5
  69. package/lib/hooks/doc-coupling-check.mjs +5 -1
  70. package/lib/hooks/edit-accumulator.mjs +25 -10
  71. package/lib/hooks/edit-error-recovery.mjs +4 -0
  72. package/lib/hooks/edit-guard.mjs +4 -0
  73. package/lib/hooks/guard-bash.mjs +4 -0
  74. package/lib/hooks/mcp-audit.mjs +4 -0
  75. package/lib/hooks/mcp-health-check.mjs +4 -0
  76. package/lib/hooks/model-fallback.mjs +7 -11
  77. package/lib/hooks/policy-engine.mjs +4 -0
  78. package/lib/hooks/post-merge-docs-check.mjs +4 -0
  79. package/lib/hooks/post-merge-tracking.mjs +82 -0
  80. package/lib/hooks/pre-compact.mjs +4 -0
  81. package/lib/hooks/pre-push-gate.mjs +84 -231
  82. package/lib/hooks/proactive-activation.mjs +5 -2
  83. package/lib/hooks/readme-age-check.mjs +4 -0
  84. package/lib/hooks/registry-sync.mjs +35 -20
  85. package/lib/hooks/rule-verifier.mjs +3 -0
  86. package/lib/hooks/scan-secrets.mjs +4 -0
  87. package/lib/hooks/session-optimize.mjs +4 -0
  88. package/lib/hooks/session-reflect.mjs +4 -0
  89. package/lib/hooks/session-start.mjs +49 -2
  90. package/lib/hooks/session-tracking-refresh.mjs +70 -0
  91. package/lib/hooks/stop-notify.mjs +13 -2
  92. package/lib/hooks/stop-typecheck.mjs +4 -0
  93. package/lib/hooks/test-watch.mjs +8 -4
  94. package/lib/ingest/chunker.mjs +94 -0
  95. package/lib/ingest/pipeline.mjs +53 -0
  96. package/lib/ingest/store.mjs +82 -0
  97. package/lib/init-unified.mjs +90 -23
  98. package/lib/intake/attribution.mjs +77 -0
  99. package/lib/intake/intake-config.mjs +3 -0
  100. package/lib/intake/manifest.mjs +107 -0
  101. package/lib/intake/poll-lock.mjs +136 -0
  102. package/lib/intake/prepare.mjs +42 -4
  103. package/lib/knowledge/search.mjs +12 -0
  104. package/lib/logging/rotate.mjs +394 -0
  105. package/lib/mcp/server.mjs +142 -1
  106. package/lib/mcp/tools/project.mjs +2 -2
  107. package/lib/mcp/tools/skills.mjs +6 -3
  108. package/lib/mcp/tools/telemetry.mjs +1 -1
  109. package/lib/mcp/tools/workflow.mjs +6 -2
  110. package/lib/observation-store.mjs +14 -5
  111. package/lib/ollama-manager.mjs +32 -28
  112. package/lib/opencode-config.mjs +10 -3
  113. package/lib/orchestration/routing-tables.mjs +176 -0
  114. package/lib/orchestration-policy.mjs +18 -106
  115. package/lib/parity.mjs +48 -7
  116. package/lib/profiles/lifecycle.mjs +19 -1
  117. package/lib/project-init-shared.mjs +11 -5
  118. package/lib/project-root.mjs +104 -0
  119. package/lib/prompt-composer.js +11 -1
  120. package/lib/roles/catalog.mjs +1 -1
  121. package/lib/roles/event-bus.mjs +29 -9
  122. package/lib/roles/router.mjs +8 -7
  123. package/lib/runtime/uv-bootstrap.mjs +129 -0
  124. package/lib/runtime/whisper-bootstrap.mjs +102 -0
  125. package/lib/server/index.mjs +53 -10
  126. package/lib/server/static/index.html +1 -15
  127. package/lib/specialists/postconditions.mjs +1 -1
  128. package/lib/status.mjs +1 -1
  129. package/lib/storage/backup.mjs +2 -2
  130. package/lib/sync/skill-frontmatter.mjs +113 -21
  131. package/lib/telemetry/intent-verifications.mjs +16 -3
  132. package/lib/telemetry/skill-calls.mjs +12 -3
  133. package/lib/tracking-surfaces.mjs +377 -0
  134. package/lib/validators/skills.mjs +86 -54
  135. package/lib/worker/trace.mjs +19 -2
  136. package/package.json +10 -6
  137. package/personas/construct.md +4 -7
  138. package/platforms/claude/settings.template.json +29 -28
  139. package/rules/common/beads-hygiene.md +3 -9
  140. package/rules/common/code-review.md +3 -6
  141. package/rules/common/coding-style.md +3 -6
  142. package/rules/common/comments.md +3 -7
  143. package/rules/common/commit-approval.md +3 -6
  144. package/rules/common/cx-agent-routing.md +3 -7
  145. package/rules/common/cx-skill-routing.md +3 -3
  146. package/rules/common/doc-ownership.md +3 -8
  147. package/rules/common/efficiency.md +3 -8
  148. package/rules/common/framing.md +3 -8
  149. package/rules/common/git-workflow.md +3 -5
  150. package/rules/common/no-fabrication.md +4 -12
  151. package/rules/common/patterns.md +3 -5
  152. package/rules/common/release-gates.md +3 -8
  153. package/rules/common/research.md +3 -8
  154. package/rules/common/review-before-change.md +3 -9
  155. package/rules/common/security.md +3 -6
  156. package/rules/common/skill-composition.md +3 -7
  157. package/rules/common/testing.md +3 -6
  158. package/rules/golang/coding-style.md +1 -5
  159. package/rules/golang/hooks.md +1 -5
  160. package/rules/golang/patterns.md +1 -5
  161. package/rules/golang/security.md +1 -5
  162. package/rules/golang/testing.md +1 -5
  163. package/rules/python/coding-style.md +1 -5
  164. package/rules/python/hooks.md +1 -5
  165. package/rules/python/patterns.md +1 -5
  166. package/rules/python/security.md +1 -5
  167. package/rules/python/testing.md +1 -5
  168. package/rules/swift/coding-style.md +1 -5
  169. package/rules/swift/hooks.md +1 -5
  170. package/rules/swift/patterns.md +1 -5
  171. package/rules/swift/security.md +1 -5
  172. package/rules/swift/testing.md +1 -5
  173. package/rules/typescript/coding-style.md +1 -5
  174. package/rules/typescript/hooks.md +1 -5
  175. package/rules/typescript/patterns.md +1 -5
  176. package/rules/typescript/security.md +1 -5
  177. package/rules/typescript/testing.md +1 -5
  178. package/rules/web/coding-style.md +3 -5
  179. package/rules/web/design-quality.md +3 -5
  180. package/rules/web/hooks.md +3 -5
  181. package/rules/web/patterns.md +3 -5
  182. package/rules/web/performance.md +3 -5
  183. package/rules/web/security.md +3 -5
  184. package/rules/web/testing.md +3 -5
  185. package/scripts/sync-specialists.mjs +269 -75
  186. package/skills/ai/agent-dev.md +4 -5
  187. package/skills/ai/llm-security.md +4 -5
  188. package/skills/ai/ml-ops.md +4 -5
  189. package/skills/ai/orchestration-workflow.md +4 -5
  190. package/skills/ai/prompt-and-eval.md +4 -5
  191. package/skills/ai/prompt-optimizer.md +4 -6
  192. package/skills/ai/rag-system.md +4 -5
  193. package/skills/architecture/api-design.md +4 -5
  194. package/skills/architecture/caching.md +4 -5
  195. package/skills/architecture/cloud-native.md +4 -5
  196. package/skills/architecture/message-queue.md +4 -5
  197. package/skills/architecture/security-arch.md +4 -5
  198. package/skills/compliance/ai-disclosure.md +4 -5
  199. package/skills/compliance/data-privacy.md +4 -5
  200. package/skills/compliance/license-audit.md +4 -5
  201. package/skills/compliance/regulatory-review.md +4 -5
  202. package/skills/development/cpp.md +4 -5
  203. package/skills/development/go.md +4 -5
  204. package/skills/development/java.md +4 -5
  205. package/skills/development/kotlin.md +4 -5
  206. package/skills/development/mobile-crossplatform.md +4 -5
  207. package/skills/development/python.md +4 -5
  208. package/skills/development/rust.md +4 -5
  209. package/skills/development/shell.md +4 -5
  210. package/skills/development/swift.md +4 -5
  211. package/skills/development/typescript.md +4 -5
  212. package/skills/devops/ci-cd.md +4 -5
  213. package/skills/devops/containerization.md +4 -5
  214. package/skills/devops/cost-optimization.md +4 -5
  215. package/skills/devops/data-engineering.md +4 -5
  216. package/skills/devops/database.md +4 -5
  217. package/skills/devops/dependency-management.md +4 -5
  218. package/skills/devops/devsecops.md +4 -5
  219. package/skills/devops/git-workflow.md +4 -5
  220. package/skills/devops/incident-response.md +4 -5
  221. package/skills/devops/monorepo.md +4 -5
  222. package/skills/devops/observability.md +4 -5
  223. package/skills/devops/performance.md +4 -5
  224. package/skills/devops/testing.md +4 -5
  225. package/skills/docs/adr-workflow.md +4 -7
  226. package/skills/docs/backlog-proposal-workflow.md +4 -3
  227. package/skills/docs/customer-profile-workflow.md +4 -3
  228. package/skills/docs/document-ingest-workflow.md +4 -3
  229. package/skills/docs/evidence-ingest-workflow.md +4 -3
  230. package/skills/docs/init-docs.md +4 -5
  231. package/skills/docs/init-project.md +4 -5
  232. package/skills/docs/prd-workflow.md +4 -7
  233. package/skills/docs/prfaq-workflow.md +4 -3
  234. package/skills/docs/product-intelligence-review.md +4 -3
  235. package/skills/docs/product-intelligence-workflow.md +4 -6
  236. package/skills/docs/product-signal-workflow.md +4 -5
  237. package/skills/docs/research-workflow.md +4 -5
  238. package/skills/docs/runbook-workflow.md +4 -5
  239. package/skills/docs/strategy-workflow.md +4 -5
  240. package/skills/exploration/dependency-graph-reading.md +4 -7
  241. package/skills/exploration/repo-map.md +4 -5
  242. package/skills/exploration/tracer-bullet-method.md +4 -7
  243. package/skills/exploration/unknown-codebase-onboarding.md +4 -7
  244. package/skills/frameworks/django.md +4 -5
  245. package/skills/frameworks/nextjs.md +4 -5
  246. package/skills/frameworks/react.md +4 -5
  247. package/skills/frameworks/spring-boot.md +4 -5
  248. package/skills/frontend-design/accessibility.md +4 -5
  249. package/skills/frontend-design/component-patterns.md +4 -5
  250. package/skills/frontend-design/engineering.md +4 -5
  251. package/skills/frontend-design/state-management.md +4 -5
  252. package/skills/frontend-design/ui-aesthetics.md +4 -5
  253. package/skills/frontend-design/ux-principles.md +4 -5
  254. package/skills/operating/change-management.md +4 -8
  255. package/skills/operating/incident-response.md +4 -8
  256. package/skills/operating/oncall-rotation.md +4 -7
  257. package/skills/operating/orchestration-reference.md +4 -10
  258. package/skills/quality-gates/review-work.md +4 -5
  259. package/skills/quality-gates/verify-change.md +4 -5
  260. package/skills/quality-gates/verify-module.md +4 -5
  261. package/skills/quality-gates/verify-quality.md +4 -5
  262. package/skills/quality-gates/verify-security.md +4 -5
  263. package/skills/roles/architect.ai-systems.md +6 -9
  264. package/skills/roles/architect.data.md +6 -9
  265. package/skills/roles/architect.enterprise.md +6 -9
  266. package/skills/roles/architect.integration.md +6 -9
  267. package/skills/roles/architect.md +7 -14
  268. package/skills/roles/architect.platform.md +6 -9
  269. package/skills/roles/data-analyst.experiment.md +6 -9
  270. package/skills/roles/data-analyst.md +6 -9
  271. package/skills/roles/data-analyst.product-intelligence.md +7 -9
  272. package/skills/roles/data-analyst.product.md +6 -9
  273. package/skills/roles/data-analyst.telemetry.md +7 -9
  274. package/skills/roles/data-engineer.pipeline.md +6 -9
  275. package/skills/roles/data-engineer.vector-retrieval.md +7 -9
  276. package/skills/roles/data-engineer.warehouse.md +6 -9
  277. package/skills/roles/debugger.md +6 -9
  278. package/skills/roles/designer.accessibility.md +6 -9
  279. package/skills/roles/designer.md +7 -9
  280. package/skills/roles/engineer.ai.md +6 -9
  281. package/skills/roles/engineer.data.md +6 -9
  282. package/skills/roles/engineer.md +9 -9
  283. package/skills/roles/engineer.platform.md +6 -9
  284. package/skills/roles/operator.docs.md +6 -9
  285. package/skills/roles/operator.md +9 -9
  286. package/skills/roles/operator.release.md +6 -9
  287. package/skills/roles/operator.sre.md +6 -9
  288. package/skills/roles/orchestrator.md +6 -9
  289. package/skills/roles/product-manager.ai-product.md +6 -9
  290. package/skills/roles/product-manager.business-strategy.md +6 -9
  291. package/skills/roles/product-manager.enterprise.md +6 -9
  292. package/skills/roles/product-manager.growth.md +7 -9
  293. package/skills/roles/product-manager.md +7 -9
  294. package/skills/roles/product-manager.platform.md +6 -9
  295. package/skills/roles/product-manager.product.md +6 -9
  296. package/skills/roles/qa.ai-eval.md +8 -9
  297. package/skills/roles/qa.api-contract.md +7 -9
  298. package/skills/roles/qa.data-pipeline.md +7 -9
  299. package/skills/roles/qa.md +7 -9
  300. package/skills/roles/qa.test-automation.md +6 -9
  301. package/skills/roles/qa.web-ui.md +7 -9
  302. package/skills/roles/researcher.explorer.md +6 -9
  303. package/skills/roles/researcher.md +8 -9
  304. package/skills/roles/researcher.ux.md +6 -9
  305. package/skills/roles/reviewer.devil-advocate.md +6 -9
  306. package/skills/roles/reviewer.evaluator.md +6 -9
  307. package/skills/roles/reviewer.md +9 -9
  308. package/skills/roles/reviewer.trace.md +6 -9
  309. package/skills/roles/security.ai.md +7 -9
  310. package/skills/roles/security.appsec.md +6 -9
  311. package/skills/roles/security.cloud.md +6 -9
  312. package/skills/roles/security.legal-compliance.md +6 -9
  313. package/skills/roles/security.md +7 -9
  314. package/skills/roles/security.privacy.md +7 -9
  315. package/skills/roles/security.supply-chain.md +7 -9
  316. package/skills/security/blue-team.md +4 -5
  317. package/skills/security/code-audit.md +4 -5
  318. package/skills/security/pentest.md +4 -5
  319. package/skills/security/red-team.md +4 -5
  320. package/skills/security/threat-intel.md +4 -5
  321. package/skills/security/vuln-research.md +4 -5
  322. package/skills/strategy/competitive-landscape.md +4 -8
  323. package/skills/strategy/market-research-methods.md +4 -8
  324. package/skills/strategy/narrative-arc.md +4 -8
  325. package/skills/strategy/pricing-positioning.md +4 -8
  326. package/skills/utility/clean-code.md +4 -5
  327. package/specialists/policy-inventory.json +14 -0
  328. package/specialists/registry.json +158 -13
  329. package/lib/hooks/env-check.mjs +0 -83
  330. package/lib/hooks/read-tracker.mjs +0 -61
  331. package/lib/policy/unified-gates.mjs +0 -96
  332. package/lib/server/static/assets/index-ab25c707.js +0 -70
  333. package/lib/server/static/assets/index-f0c80a2b.css +0 -1
  334. package/lib/specialist-contracts-enforce.mjs +0 -158
  335. package/rules/common/agents.md +0 -28
  336. package/rules/common/development-workflow.md +0 -32
  337. 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
- }
@@ -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