@geraldmaron/construct 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +9 -6
- package/LICENSE +201 -21
- package/README.md +132 -257
- package/agents/contracts.json +387 -0
- package/agents/prompts/cx-accessibility.md +8 -0
- package/agents/prompts/cx-ai-engineer.md +92 -0
- package/agents/prompts/cx-architect.md +10 -2
- package/agents/prompts/cx-business-strategist.md +13 -0
- package/agents/prompts/cx-data-analyst.md +80 -0
- package/agents/prompts/cx-data-engineer.md +4 -0
- package/agents/prompts/cx-debugger.md +8 -0
- package/agents/prompts/cx-designer.md +19 -0
- package/agents/prompts/cx-devil-advocate.md +4 -0
- package/agents/prompts/cx-docs-keeper.md +128 -0
- package/agents/prompts/cx-engineer.md +13 -0
- package/agents/prompts/cx-evaluator.md +4 -0
- package/agents/prompts/cx-explorer.md +12 -0
- package/agents/prompts/cx-legal-compliance.md +13 -0
- package/agents/prompts/cx-operations.md +13 -0
- package/agents/prompts/cx-orchestrator.md +107 -4
- package/agents/prompts/cx-platform-engineer.md +75 -0
- package/agents/prompts/cx-product-manager.md +8 -0
- package/agents/prompts/cx-qa.md +100 -0
- package/agents/prompts/cx-rd-lead.md +13 -0
- package/agents/prompts/cx-release-manager.md +8 -0
- package/agents/prompts/cx-researcher.md +21 -1
- package/agents/prompts/cx-reviewer.md +8 -0
- package/agents/prompts/cx-security.md +104 -0
- package/agents/prompts/cx-sre.md +104 -0
- package/agents/prompts/cx-test-automation.md +4 -0
- package/agents/prompts/cx-trace-reviewer.md +7 -3
- package/agents/prompts/cx-ux-researcher.md +4 -0
- package/agents/registry.json +365 -90
- package/agents/role-manifests.json +217 -0
- package/bin/construct +3345 -141
- package/bin/construct-postinstall.mjs +87 -0
- package/commands/build/feature.md +6 -6
- package/commands/plan/feature.md +6 -5
- package/commands/plan/requirements.md +1 -1
- package/commands/ship/status.md +1 -1
- package/commands/work/drive.md +3 -3
- package/commands/work/optimize-prompts.md +3 -3
- package/db/{migrations → schema}/001_init.sql +2 -0
- package/db/schema/002_pgvector.sql +182 -0
- package/db/schema/003_intake.sql +47 -0
- package/examples/README.md +85 -0
- package/examples/internal/roles/architect/bad/clever-plan-without-contracts.md +30 -0
- package/examples/internal/roles/architect/golden/explicit-tradeoff-before-plan.md +23 -0
- package/examples/internal/roles/engineer/bad/speculative-abstraction.md +30 -0
- package/examples/internal/roles/engineer/golden/read-before-write.md +28 -0
- package/examples/internal/roles/orchestrator/bad/everything-becomes-multi-agent.md +29 -0
- package/examples/internal/roles/orchestrator/golden/minimal-dispatch.md +22 -0
- package/examples/internal/roles/qa/bad/coverage-theater.md +30 -0
- package/examples/internal/roles/qa/golden/regression-gate.md +23 -0
- package/examples/internal/roles/reviewer/bad/lgtm-without-verification.md +29 -0
- package/examples/internal/roles/reviewer/golden/find-structural-risk-first.md +28 -0
- package/examples/personas/construct/adversarial/ignore-instruction-to-skip-approval.md +22 -0
- package/examples/personas/construct/bad/commit-without-approval.md +30 -0
- package/examples/personas/construct/boundary/blocked-needs-main-input.md +29 -0
- package/examples/personas/construct/golden/branch-approval-before-mutation.md +36 -0
- package/examples/personas/construct/golden/focused-direct-answer.md +28 -0
- package/examples/provider-plugin/README.md +34 -0
- package/examples/provider-plugin/index.mjs +74 -0
- package/examples/provider-plugin/package.json +15 -0
- package/examples/seed-observations/README.md +38 -0
- package/examples/seed-observations/anti-patterns.md +44 -0
- package/examples/seed-observations/decisions.md +36 -0
- package/examples/seed-observations/patterns.md +42 -0
- package/lib/agent-contracts-enforce.mjs +158 -0
- package/lib/agent-contracts.mjs +231 -0
- package/lib/agents/postconditions.mjs +126 -0
- package/lib/agents/schema.mjs +124 -0
- package/lib/artifact-capture.mjs +183 -0
- package/lib/audit-trail.mjs +149 -0
- package/lib/auto-docs.mjs +245 -65
- package/lib/beads/auto-close.mjs +126 -0
- package/lib/beads/drift.mjs +171 -0
- package/lib/beads-automation.mjs +542 -0
- package/lib/beads-client.mjs +518 -0
- package/lib/beads-lock.mjs +377 -0
- package/lib/beads-optimistic.mjs +365 -0
- package/lib/bootstrap/built-ins.mjs +136 -0
- package/lib/bootstrap/lazy-install.mjs +161 -0
- package/lib/bootstrap/resources.mjs +120 -0
- package/lib/bootstrap.mjs +105 -0
- package/lib/cache-governor.js +213 -0
- package/lib/cache-strategy-anthropic.js +62 -0
- package/lib/cache-strategy-google.js +79 -0
- package/lib/cache-strategy-none.js +30 -0
- package/lib/cache-strategy-openai.js +48 -0
- package/lib/cache-strategy.js +91 -0
- package/lib/claude-allow.mjs +149 -0
- package/lib/cli-commands.mjs +413 -258
- package/lib/codex-config.mjs +3 -1
- package/lib/comment-lint.mjs +55 -6
- package/lib/completions.mjs +21 -6
- package/lib/config/alias.mjs +56 -0
- package/lib/config/project-config.mjs +335 -0
- package/lib/config/schema.mjs +159 -0
- package/lib/context-router.mjs +308 -0
- package/lib/cost-ledger.mjs +177 -0
- package/lib/cost.mjs +171 -10
- package/lib/dashboard-static.mjs +158 -0
- package/lib/deployment-mode.mjs +86 -0
- package/lib/deprecate.mjs +49 -0
- package/lib/dispatch-batch.js +183 -0
- package/lib/distill.mjs +21 -8
- package/lib/doc-stamp.mjs +164 -0
- package/lib/doc-verify.mjs +119 -0
- package/lib/docs-routing.mjs +89 -0
- package/lib/docs-verify.mjs +417 -0
- package/lib/doctor/audit.mjs +71 -0
- package/lib/doctor/cli.mjs +99 -0
- package/lib/doctor/escalate.mjs +29 -0
- package/lib/doctor/index.mjs +140 -0
- package/lib/doctor/report.mjs +170 -0
- package/lib/doctor/watchers/bd-watch.mjs +117 -0
- package/lib/doctor/watchers/cost.mjs +130 -0
- package/lib/doctor/watchers/disk.mjs +122 -0
- package/lib/doctor/watchers/handoffs.mjs +33 -0
- package/lib/doctor/watchers/process-pressure.mjs +60 -0
- package/lib/doctor/watchers/service-health.mjs +188 -0
- package/lib/document-extract.mjs +288 -0
- package/lib/document-ingest.mjs +230 -0
- package/lib/drop.mjs +282 -0
- package/lib/embed/approval-queue.mjs +176 -0
- package/lib/embed/artifact.mjs +349 -0
- package/lib/embed/authority-guard.mjs +155 -0
- package/lib/embed/cli.mjs +408 -0
- package/lib/embed/config.mjs +355 -0
- package/lib/embed/conflict-detection.mjs +264 -0
- package/lib/embed/customer-profiles.mjs +480 -0
- package/lib/embed/daemon.mjs +1309 -0
- package/lib/embed/demand-fetch.mjs +449 -0
- package/lib/embed/docs-lifecycle.mjs +349 -0
- package/lib/embed/inbox-live-watcher.mjs +119 -0
- package/lib/embed/inbox.mjs +343 -0
- package/lib/embed/intake-metrics.mjs +190 -0
- package/lib/embed/jobs/vector-sync.mjs +198 -0
- package/lib/embed/notifications.mjs +75 -0
- package/lib/embed/output.mjs +79 -0
- package/lib/embed/providers/github.mjs +295 -0
- package/lib/embed/providers/jira.mjs +192 -0
- package/lib/embed/providers/linear.mjs +186 -0
- package/lib/embed/providers/registry.mjs +115 -0
- package/lib/embed/providers/slack.mjs +203 -0
- package/lib/embed/recommendation-store.mjs +378 -0
- package/lib/embed/roadmap.mjs +374 -0
- package/lib/embed/role-framing.mjs +110 -0
- package/lib/embed/scheduler.mjs +99 -0
- package/lib/embed/semantic.mjs +325 -0
- package/lib/embed/snapshot.mjs +191 -0
- package/lib/embed/supervision.mjs +235 -0
- package/lib/embed/target-resolver.mjs +186 -0
- package/lib/embed/worker.mjs +62 -0
- package/lib/embed/workspaces.mjs +297 -0
- package/lib/engine/chunker-headings.mjs +110 -0
- package/lib/engine/compressor-heuristic.mjs +100 -0
- package/lib/engine/consolidate.mjs +287 -0
- package/lib/engine/contracts.mjs +126 -0
- package/lib/engine/defaults.mjs +129 -0
- package/lib/engine/eval-retrieval.mjs +148 -0
- package/lib/engine/fuser-rrf.mjs +62 -0
- package/lib/engine/index.mjs +37 -0
- package/lib/engine/registry.mjs +146 -0
- package/lib/engine/reranker-mmr.mjs +90 -0
- package/lib/engine/tokens.mjs +77 -0
- package/lib/entity-store.mjs +280 -0
- package/lib/env-config.mjs +69 -4
- package/lib/evals/retrieval-bench.mjs +159 -0
- package/lib/evaluator-optimizer.mjs +317 -0
- package/lib/features.mjs +159 -29
- package/lib/gates-audit.mjs +236 -0
- package/lib/git-hooks/prepare-commit-msg +58 -0
- package/lib/handoffs/cleanup.mjs +159 -0
- package/lib/handoffs/contract.mjs +162 -0
- package/lib/handoffs/inventory.mjs +120 -0
- package/lib/headhunt.mjs +28 -47
- package/lib/health-check.mjs +399 -0
- package/lib/hook-health.mjs +442 -0
- package/lib/hooks/_lib/log.mjs +82 -0
- package/lib/hooks/adaptive-lint.mjs +26 -2
- package/lib/hooks/agent-tracker.mjs +171 -14
- package/lib/hooks/audit-reads.mjs +109 -0
- package/lib/hooks/audit-trail.mjs +153 -0
- package/lib/hooks/bash-output-logger.mjs +71 -0
- package/lib/hooks/block-no-verify.mjs +41 -0
- package/lib/hooks/ci-status-check.mjs +82 -0
- package/lib/hooks/comment-lint.mjs +29 -7
- package/lib/hooks/config-protection.mjs +39 -18
- package/lib/hooks/context-watch.mjs +137 -0
- package/lib/hooks/context-window-recovery.mjs +4 -20
- package/lib/hooks/dep-audit.mjs +16 -0
- package/lib/hooks/doc-coupling-check.mjs +80 -0
- package/lib/hooks/edit-accumulator.mjs +3 -0
- package/lib/hooks/edit-error-recovery.mjs +3 -0
- package/lib/hooks/edit-guard.mjs +45 -4
- package/lib/hooks/env-check.mjs +3 -0
- package/lib/hooks/guard-bash.mjs +58 -1
- package/lib/hooks/mcp-audit.mjs +18 -20
- package/lib/hooks/mcp-health-check.mjs +36 -0
- package/lib/hooks/model-fallback.mjs +42 -56
- package/lib/hooks/policy-engine.mjs +209 -0
- package/lib/hooks/post-merge-docs-check.mjs +63 -0
- package/lib/hooks/pre-compact.mjs +4 -24
- package/lib/hooks/pre-push-gate.mjs +200 -37
- package/lib/hooks/proactive-activation.mjs +284 -0
- package/lib/hooks/read-tracker.mjs +27 -4
- package/lib/hooks/readme-age-check.mjs +77 -0
- package/lib/hooks/registry-sync.mjs +12 -5
- package/lib/hooks/scan-secrets.mjs +50 -7
- package/lib/hooks/session-optimize.mjs +311 -0
- package/lib/hooks/session-start.mjs +287 -28
- package/lib/hooks/stop-notify.mjs +236 -96
- package/lib/hooks/stop-typecheck.mjs +13 -1
- package/lib/hooks/test-watch.mjs +68 -0
- package/lib/host-capabilities.mjs +31 -10
- package/lib/init-docs.mjs +731 -291
- package/lib/init-unified.mjs +1000 -0
- package/lib/init-update.mjs +168 -0
- package/lib/init.mjs +107 -0
- package/lib/install/first-invocation.mjs +119 -0
- package/lib/install/stage-project.mjs +69 -0
- package/lib/intake/classify.mjs +278 -0
- package/lib/intake/feedback.mjs +273 -0
- package/lib/intake/filesystem-queue.mjs +158 -0
- package/lib/intake/intake-config.mjs +132 -0
- package/lib/intake/postgres-queue.mjs +198 -0
- package/lib/intake/prepare.mjs +139 -0
- package/lib/intake/queue.mjs +83 -0
- package/lib/intake/session-prelude.mjs +50 -0
- package/lib/integrations/intake-integrations.mjs +740 -0
- package/lib/intent-classifier.mjs +253 -0
- package/lib/knowledge/layout.mjs +72 -0
- package/lib/knowledge/rag.mjs +331 -0
- package/lib/knowledge/search.mjs +315 -0
- package/lib/knowledge/trends.mjs +261 -0
- package/lib/logger.mjs +85 -0
- package/lib/mcp/broker.mjs +124 -0
- package/lib/mcp/server.mjs +554 -854
- package/lib/mcp/tools/document.mjs +132 -0
- package/lib/mcp/tools/memory.mjs +209 -0
- package/lib/mcp/tools/project.mjs +349 -0
- package/lib/mcp/tools/skills.mjs +409 -0
- package/lib/mcp/tools/storage.mjs +60 -0
- package/lib/mcp/tools/telemetry.mjs +315 -0
- package/lib/mcp/tools/workflow.mjs +112 -0
- package/lib/mcp-catalog.json +54 -3
- package/lib/mcp-manager.mjs +96 -48
- package/lib/mcp-platform-config.mjs +22 -22
- package/lib/memory-stats.mjs +121 -0
- package/lib/mode-commands.mjs +124 -0
- package/lib/model-free-selector.mjs +184 -0
- package/lib/model-pricing.mjs +152 -0
- package/lib/model-registry.mjs +226 -0
- package/lib/model-router.mjs +362 -386
- package/lib/observation-store.mjs +391 -0
- package/lib/ollama-manager.mjs +428 -0
- package/lib/opencode-config.mjs +13 -3
- package/lib/opencode-runtime-plugin.mjs +70 -38
- package/lib/opencode-telemetry.mjs +64 -6
- package/lib/orchestration-policy.mjs +509 -6
- package/lib/overrides/resolver.mjs +207 -0
- package/lib/parity.mjs +147 -0
- package/lib/paths.mjs +33 -0
- package/lib/performance/generate.mjs +212 -0
- package/lib/plugin-registry.mjs +268 -0
- package/lib/policy/engine.mjs +130 -0
- package/lib/policy/unified-gates.mjs +96 -0
- package/lib/project-detection.mjs +129 -0
- package/lib/project-init-shared.mjs +272 -0
- package/lib/project-profile.mjs +447 -0
- package/lib/prompt-composer.js +434 -0
- package/lib/prompt-metadata.mjs +1 -1
- package/lib/provider-capabilities-anthropic.js +44 -0
- package/lib/provider-capabilities-deepseek.js +37 -0
- package/lib/provider-capabilities-generic.js +26 -0
- package/lib/provider-capabilities-google.js +47 -0
- package/lib/provider-capabilities-openai.js +45 -0
- package/lib/provider-capabilities.js +142 -0
- package/lib/providers/atlassian-confluence/index.mjs +103 -0
- package/lib/providers/atlassian-jira/index.mjs +100 -0
- package/lib/providers/auth-manager.mjs +126 -0
- package/lib/providers/circuit-breaker.mjs +124 -0
- package/lib/providers/contract.mjs +93 -0
- package/lib/providers/github/index.mjs +126 -0
- package/lib/providers/registry.mjs +184 -0
- package/lib/providers/salesforce/index.mjs +100 -0
- package/lib/providers/slack/index.mjs +80 -0
- package/lib/reflect.mjs +137 -0
- package/lib/research-lint.mjs +164 -0
- package/lib/resources/budget.mjs +259 -0
- package/lib/role-preload.mjs +21 -6
- package/lib/roles/approval-surface.mjs +54 -0
- package/lib/roles/cli.mjs +118 -0
- package/lib/roles/event-bus.mjs +79 -0
- package/lib/roles/fence.mjs +84 -0
- package/lib/roles/gateway.mjs +260 -0
- package/lib/roles/hook-emit.mjs +37 -0
- package/lib/roles/manifest.mjs +48 -0
- package/lib/roles/router.mjs +27 -0
- package/lib/runtime-pressure.mjs +360 -0
- package/lib/schema-artifact.mjs +134 -0
- package/lib/schema-infer.mjs +551 -0
- package/lib/server/auth.mjs +168 -0
- package/lib/server/chat.mjs +336 -0
- package/lib/server/cors.mjs +77 -0
- package/lib/server/csrf.mjs +91 -0
- package/lib/server/index.mjs +1927 -78
- package/lib/server/insights.mjs +765 -0
- package/lib/server/rate-limit.mjs +91 -0
- package/lib/server/static/assets/index-ab25c707.js +70 -0
- package/lib/server/static/assets/index-f0c80a2b.css +1 -0
- package/lib/server/static/index.html +12 -817
- package/lib/server/telemetry-login.mjs +108 -0
- package/lib/server/webhook.mjs +510 -0
- package/lib/service-manager.mjs +522 -58
- package/lib/services/pattern-promotion-service.mjs +167 -0
- package/lib/services/telemetry-backend.mjs +178 -0
- package/lib/session-store.mjs +374 -0
- package/lib/setup-prompts.mjs +96 -0
- package/lib/setup.mjs +523 -36
- package/lib/skills-apply.mjs +280 -0
- package/lib/skills-scope.mjs +118 -0
- package/lib/status.mjs +261 -70
- package/lib/storage/admin.mjs +355 -0
- package/lib/storage/backend.mjs +2 -1
- package/lib/storage/backup.mjs +347 -0
- package/lib/storage/embeddings-engine.mjs +133 -0
- package/lib/storage/embeddings-legacy.mjs +85 -0
- package/lib/storage/embeddings-local.mjs +108 -0
- package/lib/storage/embeddings-ollama.mjs +78 -0
- package/lib/storage/embeddings-openai.mjs +85 -0
- package/lib/storage/embeddings.mjs +92 -33
- package/lib/storage/file-lock.mjs +130 -0
- package/lib/storage/fusion.mjs +95 -0
- package/lib/storage/hybrid-query.mjs +34 -27
- package/lib/storage/migrations.mjs +187 -0
- package/lib/storage/postgres-backup.mjs +124 -0
- package/lib/storage/sql-store.mjs +5 -15
- package/lib/storage/state-source.mjs +12 -13
- package/lib/storage/store-version.mjs +115 -0
- package/lib/storage/sync.mjs +144 -35
- package/lib/storage/unified-storage.mjs +550 -0
- package/lib/storage/vector-client.mjs +286 -0
- package/lib/storage/vector-store.mjs +71 -30
- package/lib/task-graph/generate.mjs +135 -0
- package/lib/task-graph/schema.mjs +81 -0
- package/lib/task-graph/store.mjs +71 -0
- package/lib/telemetry/backends/local.mjs +62 -0
- package/lib/telemetry/backends/{langfuse.mjs → remote.mjs} +27 -14
- package/lib/telemetry/backfill.mjs +180 -0
- package/lib/telemetry/eval-datasets.mjs +203 -0
- package/lib/telemetry/{langfuse-ingest.mjs → ingest.mjs} +26 -20
- package/lib/telemetry/intent-verifications.mjs +86 -0
- package/lib/telemetry/llm-judge.mjs +350 -0
- package/lib/telemetry/model-pricing-catalog.mjs +557 -0
- package/lib/telemetry/setup.mjs +151 -0
- package/lib/telemetry/skill-calls.mjs +78 -0
- package/lib/telemetry/team-rollup.mjs +4 -4
- package/lib/token-engine.js +117 -0
- package/lib/token-estimator-anthropic.js +15 -0
- package/lib/token-estimator-deepseek.js +13 -0
- package/lib/token-estimator-default.js +13 -0
- package/lib/token-estimator-google.js +13 -0
- package/lib/token-estimator-openai.js +13 -0
- package/lib/toolkit-env.mjs +1 -1
- package/lib/tty-prompts.mjs +211 -0
- package/lib/uninstall/uninstall.mjs +423 -0
- package/lib/update.mjs +115 -0
- package/lib/upgrade.mjs +141 -0
- package/lib/validator.mjs +51 -2
- package/lib/validators/skills.mjs +142 -0
- package/lib/wireframe.mjs +422 -0
- package/lib/worker/entrypoint.mjs +241 -0
- package/lib/worker/evidence.mjs +107 -0
- package/lib/worker/run.mjs +154 -0
- package/lib/worker/trace.mjs +182 -0
- package/lib/workflow-state.mjs +14 -18
- package/package.json +21 -8
- package/personas/construct.md +53 -51
- package/platforms/claude/CLAUDE.md +1 -1
- package/platforms/claude/settings.template.json +115 -68
- package/platforms/opencode/config.template.json +3 -7
- package/rules/common/agents.md +11 -38
- package/rules/common/beads-hygiene.md +75 -0
- package/rules/common/code-review.md +11 -100
- package/rules/common/coding-style.md +5 -3
- package/rules/common/comments.md +30 -111
- package/rules/common/commit-approval.md +53 -0
- package/rules/common/cx-agent-routing.md +1 -0
- package/rules/common/development-workflow.md +23 -41
- package/rules/common/doc-ownership.md +54 -0
- package/rules/common/efficiency.md +57 -0
- package/rules/common/framing.md +76 -0
- package/rules/common/git-workflow.md +2 -4
- package/rules/common/patterns.md +3 -7
- package/rules/common/performance.md +15 -31
- package/rules/common/release-gates.md +69 -0
- package/rules/common/research.md +107 -0
- package/rules/common/security.md +6 -6
- package/rules/common/skill-composition.md +67 -0
- package/rules/common/testing.md +15 -27
- package/rules/golang/hooks.md +0 -4
- package/rules/policy/bootstrap.yaml +11 -0
- package/rules/policy/drive.yaml +8 -0
- package/rules/policy/task.yaml +9 -0
- package/rules/policy/workflow.yaml +9 -0
- package/rules/python/hooks.md +0 -4
- package/rules/swift/hooks.md +0 -4
- package/rules/typescript/hooks.md +0 -4
- package/rules/web/hooks.md +0 -2
- package/{sync-agents.mjs → scripts/sync-agents.mjs} +306 -61
- package/skills/ai/prompt-optimizer.md +7 -7
- package/skills/compliance/ai-disclosure.md +58 -0
- package/skills/compliance/data-privacy.md +46 -0
- package/skills/compliance/license-audit.md +40 -0
- package/skills/compliance/regulatory-review.md +61 -0
- package/skills/docs/document-ingest-workflow.md +52 -0
- package/skills/docs/evidence-ingest-workflow.md +9 -0
- package/skills/docs/init-docs.md +51 -18
- package/skills/docs/product-intelligence-workflow.md +12 -0
- package/skills/docs/product-signal-workflow.md +4 -0
- package/skills/docs/research-workflow.md +23 -8
- package/skills/docs/runbook-workflow.md +1 -1
- package/skills/operating/orchestration-reference.md +151 -0
- package/skills/roles/architect.md +5 -0
- package/skills/roles/engineer.md +32 -0
- package/skills/roles/operator.md +12 -0
- package/skills/roles/reviewer.md +23 -0
- package/skills/routing.md +1 -1
- package/templates/devcontainer/Dockerfile.devcontainer +38 -0
- package/templates/devcontainer/devcontainer.json +31 -0
- package/templates/distribution/bootstrap.ps1 +142 -0
- package/templates/distribution/bootstrap.sh +196 -0
- package/templates/distribution/run.mjs +187 -0
- package/templates/docs/adr.md +44 -8
- package/templates/docs/changelog-entry.md +43 -0
- package/templates/docs/construct_guide.md +149 -0
- package/templates/docs/evidence-brief.md +2 -2
- package/templates/docs/meta-prd.md +140 -19
- package/templates/docs/onboarding.md +57 -0
- package/templates/docs/prd.md +159 -15
- package/templates/docs/research-brief.md +4 -4
- package/templates/homebrew/construct.rb +67 -0
- package/langfuse/docker-compose.yml +0 -82
- package/lib/eval-harness.mjs +0 -59
- package/lib/hooks/bootstrap-guard.mjs +0 -90
- package/lib/hooks/console-warn.mjs +0 -43
- package/lib/hooks/continuation-enforcer.mjs +0 -72
- package/lib/hooks/drive-guard.mjs +0 -89
- package/lib/hooks/mcp-task-scope.mjs +0 -47
- package/lib/hooks/task-completed-guard.mjs +0 -43
- package/lib/hooks/teammate-idle-guard.mjs +0 -54
- package/lib/hooks/workflow-guard.mjs +0 -62
- package/lib/prompt-composer.mjs +0 -196
- package/lib/review.mjs +0 -429
- package/lib/server/static/app.js +0 -841
- package/lib/telemetry/langfuse-model-sync.mjs +0 -270
- package/rules/common/hooks.md +0 -35
- package/rules/zh/README.md +0 -113
- package/rules/zh/agents.md +0 -55
- package/rules/zh/code-review.md +0 -129
- package/rules/zh/coding-style.md +0 -53
- package/rules/zh/development-workflow.md +0 -49
- package/rules/zh/git-workflow.md +0 -29
- package/rules/zh/hooks.md +0 -35
- package/rules/zh/patterns.md +0 -36
- package/rules/zh/performance.md +0 -60
- package/rules/zh/security.md +0 -34
- package/rules/zh/testing.md +0 -34
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Onboarding: {role or audience}
|
|
2
|
+
|
|
3
|
+
- **Date**: {YYYY-MM-DD}
|
|
4
|
+
- **Audience**: {engineers | product | ops | all}
|
|
5
|
+
- **Maintained by**: {name or team}
|
|
6
|
+
- **Status**: draft | current | outdated
|
|
7
|
+
|
|
8
|
+
<!--
|
|
9
|
+
Onboarding docs should be runnable, not just readable. Every step should be
|
|
10
|
+
something a new person can actually execute. Flag commands that require access
|
|
11
|
+
provisioning or credentials so they are not blocked on day one.
|
|
12
|
+
-->
|
|
13
|
+
|
|
14
|
+
## Prerequisites
|
|
15
|
+
|
|
16
|
+
<!-- Accounts, access, hardware, or tools that must be in place before starting. -->
|
|
17
|
+
|
|
18
|
+
## Local setup
|
|
19
|
+
|
|
20
|
+
<!-- Step-by-step commands to get a working local environment. Use code blocks. -->
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
# Example
|
|
24
|
+
git clone ...
|
|
25
|
+
cd ...
|
|
26
|
+
cp .env.example .env
|
|
27
|
+
npm install
|
|
28
|
+
npm run dev
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Verifying the setup
|
|
32
|
+
|
|
33
|
+
<!-- How to confirm the setup worked. Include expected output or a smoke-test command. -->
|
|
34
|
+
|
|
35
|
+
## Key concepts
|
|
36
|
+
|
|
37
|
+
<!-- The minimum mental model a new person needs to be productive. Link to architecture docs. -->
|
|
38
|
+
|
|
39
|
+
## Common workflows
|
|
40
|
+
|
|
41
|
+
<!-- The two or three things this person will do every day. Link to deeper runbooks if needed. -->
|
|
42
|
+
|
|
43
|
+
## Access provisioning
|
|
44
|
+
|
|
45
|
+
<!-- What systems need access, who to ask, and typical turnaround time. -->
|
|
46
|
+
|
|
47
|
+
## Gotchas
|
|
48
|
+
|
|
49
|
+
<!-- Known sharp edges, non-obvious configuration, common first-day mistakes. -->
|
|
50
|
+
|
|
51
|
+
## Who to ask
|
|
52
|
+
|
|
53
|
+
<!-- Owners, on-call rotations, or Slack channels for help. -->
|
|
54
|
+
|
|
55
|
+
## References
|
|
56
|
+
|
|
57
|
+
<!-- Architecture overview, runbooks, ADRs, or external docs relevant to this role. -->
|
package/templates/docs/prd.md
CHANGED
|
@@ -9,39 +9,183 @@ Use this for a product capability, user workflow, or customer-facing requirement
|
|
|
9
9
|
Use meta-prd.md instead when defining the requirements for a product system, agent,
|
|
10
10
|
process, template, evaluation loop, or operating model.
|
|
11
11
|
|
|
12
|
+
Before drafting, read rules/common/framing.md.
|
|
13
|
+
|
|
14
|
+
Owning specialist: cx-product-manager (see rules/common/doc-ownership.md).
|
|
15
|
+
Construct must route PRD authoring to cx-product-manager rather than drafting directly —
|
|
16
|
+
doing so is how requirements traceability, user grounding, and external research fire.
|
|
17
|
+
|
|
12
18
|
Write with a balance of short paragraphs, tables, and bullets. Bullets are for scans,
|
|
13
19
|
not the whole document. Keep em dashes rare; prefer commas, periods, or parentheses.
|
|
14
20
|
-->
|
|
15
21
|
|
|
22
|
+
## Summary
|
|
23
|
+
<!--
|
|
24
|
+
One paragraph (3-5 sentences) that a busy reader can use as the whole PRD.
|
|
25
|
+
What the change is, who it's for, why now, and what changes when it ships.
|
|
26
|
+
No solutions in this section that aren't decided. No ticket IDs. No team names.
|
|
27
|
+
-->
|
|
28
|
+
|
|
29
|
+
## Background
|
|
30
|
+
<!--
|
|
31
|
+
Context the reader needs to evaluate this PRD without asking around.
|
|
32
|
+
Include relevant prior work (linked PRDs, ADRs, RFCs), observed signals, and
|
|
33
|
+
the current state of the user experience or system. State what is already
|
|
34
|
+
true today so the reader can compare against the proposed change.
|
|
35
|
+
|
|
36
|
+
Cite evidence: support tickets, interviews, telemetry, sales calls, research.
|
|
37
|
+
Avoid roadmap-speak ("this is a Q3 priority"); state what is happening to users.
|
|
38
|
+
-->
|
|
39
|
+
|
|
16
40
|
## Problem
|
|
17
|
-
<!--
|
|
41
|
+
<!--
|
|
42
|
+
The specific user or business outcome that is currently blocked. One or two
|
|
43
|
+
paragraphs. State the pain, not the solution.
|
|
44
|
+
|
|
45
|
+
Must NOT reference:
|
|
46
|
+
- Jira / Linear ticket IDs or "this came from ticket X"
|
|
47
|
+
- Roadmap items, OKR line items, or quarterly goals
|
|
48
|
+
- "The team decided we should build this"
|
|
49
|
+
|
|
50
|
+
Must reference:
|
|
51
|
+
- Observed user behavior, quantitative signals, or qualitative evidence
|
|
52
|
+
- The specific outcome that is not currently achievable
|
|
53
|
+
- The constraint that makes this non-trivial today
|
|
54
|
+
-->
|
|
55
|
+
|
|
56
|
+
## Goals
|
|
57
|
+
<!--
|
|
58
|
+
What success looks like, in outcome terms. Three to five goals max. Each
|
|
59
|
+
goal is the *change* you want, not the activity. Order by importance.
|
|
60
|
+
|
|
61
|
+
Examples:
|
|
62
|
+
- Reduce p95 onboarding time from 12m to under 4m for new accounts.
|
|
63
|
+
- Eliminate the manual reconciliation step our top 20 customers do every Monday.
|
|
64
|
+
- Halve the support volume for "where is my data" questions.
|
|
65
|
+
-->
|
|
66
|
+
|
|
67
|
+
## Outcome
|
|
68
|
+
<!--
|
|
69
|
+
What is concretely different for users, the business, or the system once this
|
|
70
|
+
ships and is adopted. This is the observable end state — written from the
|
|
71
|
+
user's perspective when possible. The acceptance criteria below should be the
|
|
72
|
+
falsifiable evidence that this outcome was achieved.
|
|
73
|
+
|
|
74
|
+
A reader should be able to compare the current state (Background) to this
|
|
75
|
+
section and see the delta in plain language.
|
|
76
|
+
-->
|
|
18
77
|
|
|
19
|
-
##
|
|
20
|
-
<!-- Who experiences the problem? Segments, scale, current workaround. Cite evidence (tickets, interviews, data). -->
|
|
78
|
+
## In scope and out of scope
|
|
21
79
|
|
|
22
|
-
|
|
23
|
-
|
|
80
|
+
| | Description |
|
|
81
|
+
|---|---|
|
|
82
|
+
| **In scope** | <what this PRD covers and commits to ship> |
|
|
83
|
+
| **Out of scope** | <related work explicitly deferred — name the reason> |
|
|
84
|
+
| **Adjacent (deferred)** | <work that's a natural follow-up but not in this PRD> |
|
|
24
85
|
|
|
25
|
-
|
|
26
|
-
|
|
86
|
+
<!--
|
|
87
|
+
Be specific. "Authentication" is too vague; "OAuth login for the web dashboard,
|
|
88
|
+
not for the CLI" is right. The Out of scope list is a tool for protecting
|
|
89
|
+
schedule and reviewer attention — use it.
|
|
90
|
+
-->
|
|
27
91
|
|
|
28
|
-
##
|
|
29
|
-
|
|
92
|
+
## Phases
|
|
93
|
+
|
|
94
|
+
<!--
|
|
95
|
+
Phases are how this work ships, not how it's organized internally. Each phase
|
|
96
|
+
is independently shippable and provides observable user value (or a clearly
|
|
97
|
+
defined platform capability). Avoid "phase 1: backend, phase 2: frontend" —
|
|
98
|
+
that's a task list, not a phasing.
|
|
30
99
|
|
|
31
|
-
|
|
32
|
-
|
|
100
|
+
Each phase below holds its own goal, status, functional requirements (FR),
|
|
101
|
+
and non-functional requirements (NFR), with acceptance criteria written
|
|
102
|
+
inline next to each requirement. Use `FR-<phase>.<n>` and `NFR-<phase>.<n>`
|
|
103
|
+
so requirements can be referenced from reviews and tests.
|
|
104
|
+
|
|
105
|
+
Status values: not started | in progress | shipped | deferred.
|
|
106
|
+
|
|
107
|
+
NFR categories to consider: performance, reliability, security, privacy,
|
|
108
|
+
accessibility, observability, compliance, cost. Numeric targets where possible.
|
|
109
|
+
-->
|
|
110
|
+
|
|
111
|
+
### Phase 1 — <name>
|
|
112
|
+
|
|
113
|
+
- **Goal**: <what this phase delivers>
|
|
114
|
+
- **Status**: not started
|
|
115
|
+
|
|
116
|
+
**Functional**
|
|
117
|
+
|
|
118
|
+
- **FR-1.1** — <imperative statement of what the system must do>
|
|
119
|
+
- *Acceptance*: <observable, falsifiable condition a reviewer can check without asking the author>
|
|
120
|
+
- **FR-1.2** — <...>
|
|
121
|
+
- *Acceptance*: <...>
|
|
122
|
+
|
|
123
|
+
**Non-functional**
|
|
124
|
+
|
|
125
|
+
- **NFR-1.1** — <category>: <target with number>
|
|
126
|
+
- *Acceptance*: <how this is measured and what counts as pass>
|
|
127
|
+
|
|
128
|
+
### Phase 2 — <name>
|
|
129
|
+
|
|
130
|
+
- **Goal**: <what this phase delivers>
|
|
131
|
+
- **Status**: not started
|
|
132
|
+
|
|
133
|
+
**Functional**
|
|
134
|
+
|
|
135
|
+
- **FR-2.1** — <...>
|
|
136
|
+
- *Acceptance*: <...>
|
|
137
|
+
- **FR-2.2** — <...>
|
|
138
|
+
- *Acceptance*: <...>
|
|
139
|
+
|
|
140
|
+
**Non-functional**
|
|
141
|
+
|
|
142
|
+
- **NFR-2.1** — <category>: <target>
|
|
143
|
+
- *Acceptance*: <...>
|
|
144
|
+
|
|
145
|
+
### Phase 3 — <name>
|
|
146
|
+
|
|
147
|
+
- **Goal**: <what this phase delivers>
|
|
148
|
+
- **Status**: not started
|
|
149
|
+
|
|
150
|
+
**Functional**
|
|
151
|
+
|
|
152
|
+
- **FR-3.1** — <...>
|
|
153
|
+
- *Acceptance*: <...>
|
|
154
|
+
|
|
155
|
+
**Non-functional**
|
|
156
|
+
|
|
157
|
+
- **NFR-3.1** — <category>: <target>
|
|
158
|
+
- *Acceptance*: <...>
|
|
33
159
|
|
|
34
160
|
## Success metrics
|
|
35
|
-
<!--
|
|
161
|
+
<!--
|
|
162
|
+
How we will know this worked in production over time, beyond the per-requirement
|
|
163
|
+
acceptance criteria. Leading vs. lagging. Avoid vanity metrics.
|
|
164
|
+
-->
|
|
36
165
|
|
|
37
166
|
## Constraints
|
|
38
|
-
<!--
|
|
167
|
+
<!--
|
|
168
|
+
Budget, timeline, platform, team, legal, technical debt — anything that shapes
|
|
169
|
+
the solution and isn't a requirement.
|
|
170
|
+
-->
|
|
39
171
|
|
|
40
172
|
## Dependencies
|
|
41
|
-
<!--
|
|
173
|
+
<!--
|
|
174
|
+
Teams, services, contracts, data sources, vendor timelines. Each dependency
|
|
175
|
+
should name an owner and the date it must be ready by.
|
|
176
|
+
-->
|
|
177
|
+
|
|
178
|
+
## Risks and mitigations
|
|
179
|
+
|
|
180
|
+
| Risk | Likelihood | Impact | Mitigation |
|
|
181
|
+
|---|---|---|---|
|
|
182
|
+
| <risk> | low / med / high | low / med / high | <how this is reduced or what we accept> |
|
|
42
183
|
|
|
43
184
|
## Open questions
|
|
44
|
-
|
|
185
|
+
|
|
186
|
+
| Question | Owner | Decision needed by |
|
|
187
|
+
|---|---|---|
|
|
188
|
+
| <unknown> | <name> | <YYYY-MM-DD> |
|
|
45
189
|
|
|
46
190
|
## References
|
|
47
191
|
<!-- Linked research, prior PRDs, ADRs, tickets, designs. -->
|
|
@@ -8,13 +8,13 @@
|
|
|
8
8
|
<!-- The specific, falsifiable question this research is trying to answer. One sentence. -->
|
|
9
9
|
|
|
10
10
|
## Method
|
|
11
|
-
<!-- How the question was investigated.
|
|
11
|
+
<!-- How the question was investigated. Start order, queries run, internal paths checked, experiments performed, and systems consulted. Enough detail that another person could reproduce it. -->
|
|
12
12
|
|
|
13
13
|
## Sources
|
|
14
|
-
<!--
|
|
14
|
+
<!-- For each source record: title/path, source class (internal/primary/secondary/tertiary), version or revision if relevant, and publication/access date. Separate primary from secondary. Note where sources disagree. -->
|
|
15
15
|
|
|
16
16
|
## Findings
|
|
17
|
-
<!-- What the evidence says. Separate observation from inference. Label each finding with its confidence level. -->
|
|
17
|
+
<!-- What the evidence says. Separate observation from inference. Label each finding with its confidence level and cite the supporting source(s). -->
|
|
18
18
|
|
|
19
19
|
## Confidence
|
|
20
20
|
<!-- Per finding: high / medium / low, and why. Name the biggest unknowns. -->
|
|
@@ -26,4 +26,4 @@
|
|
|
26
26
|
<!-- What this research did not resolve. What would be needed to answer each. -->
|
|
27
27
|
|
|
28
28
|
## References
|
|
29
|
-
<!-- Full citation list. -->
|
|
29
|
+
<!-- Full citation list. Include URLs, document paths, versions, and dates. -->
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Construct — Homebrew formula template.
|
|
2
|
+
#
|
|
3
|
+
# Authoritative copy lives in the construct repo at templates/homebrew/
|
|
4
|
+
# construct.rb. The tap repo (geraldmaron/homebrew-construct) carries the
|
|
5
|
+
# active formula at Formula/construct.rb and is updated by the release
|
|
6
|
+
# workflow's Homebrew bump step on every tag push.
|
|
7
|
+
#
|
|
8
|
+
# When the release pipeline fires for `vX.Y.Z`, dawidd6/action-homebrew-bump-
|
|
9
|
+
# formula rewrites the url + sha256 fields for each platform from the
|
|
10
|
+
# matching GitHub Release asset. The placeholder SHAs below are only used
|
|
11
|
+
# when seeding the tap by hand the first time.
|
|
12
|
+
class Construct < Formula
|
|
13
|
+
desc "Deployable AI R&D operating system for coding agents — runs locally or for teams"
|
|
14
|
+
homepage "https://github.com/geraldmaron/construct"
|
|
15
|
+
version "0.1.0"
|
|
16
|
+
license "Elastic-2.0"
|
|
17
|
+
|
|
18
|
+
livecheck do
|
|
19
|
+
url :stable
|
|
20
|
+
strategy :github_latest
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
on_macos do
|
|
24
|
+
on_arm do
|
|
25
|
+
url "https://github.com/geraldmaron/construct/releases/download/v0.1.0/construct-darwin-arm64"
|
|
26
|
+
sha256 "REPLACE_ON_FIRST_RELEASE_DARWIN_ARM64"
|
|
27
|
+
end
|
|
28
|
+
on_intel do
|
|
29
|
+
url "https://github.com/geraldmaron/construct/releases/download/v0.1.0/construct-darwin-x64"
|
|
30
|
+
sha256 "REPLACE_ON_FIRST_RELEASE_DARWIN_X64"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
on_linux do
|
|
35
|
+
on_arm do
|
|
36
|
+
url "https://github.com/geraldmaron/construct/releases/download/v0.1.0/construct-linux-arm64"
|
|
37
|
+
sha256 "REPLACE_ON_FIRST_RELEASE_LINUX_ARM64"
|
|
38
|
+
end
|
|
39
|
+
on_intel do
|
|
40
|
+
url "https://github.com/geraldmaron/construct/releases/download/v0.1.0/construct-linux-x64"
|
|
41
|
+
sha256 "REPLACE_ON_FIRST_RELEASE_LINUX_X64"
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def install
|
|
46
|
+
bin.install Dir["construct-*"].first => "construct"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def caveats
|
|
50
|
+
<<~EOS
|
|
51
|
+
To finish setup on this machine, run:
|
|
52
|
+
construct setup
|
|
53
|
+
|
|
54
|
+
Construct uses a local Postgres container (via Docker) for hybrid
|
|
55
|
+
retrieval. If Docker is not installed, Construct falls back to a JSON
|
|
56
|
+
vector index — no hard requirement.
|
|
57
|
+
|
|
58
|
+
To wire up hooks and agents per project, add Construct as a dev
|
|
59
|
+
dependency in that project:
|
|
60
|
+
npm install -D @geraldmaron/construct
|
|
61
|
+
EOS
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
test do
|
|
65
|
+
assert_match version.to_s, shell_output("#{bin}/construct version")
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
# Construct — Langfuse Self-Hosted
|
|
2
|
-
# Auto-provisioned: keys are seeded at container startup via LANGFUSE_INIT_* vars.
|
|
3
|
-
# No browser setup required. 'construct setup' writes keys to .env automatically.
|
|
4
|
-
#
|
|
5
|
-
# Manual usage:
|
|
6
|
-
# docker-compose -f langfuse/docker-compose.yml -p construct-langfuse up -d
|
|
7
|
-
# # Keys are ready immediately — see LANGFUSE_INIT_PROJECT_* below
|
|
8
|
-
|
|
9
|
-
name: construct-langfuse
|
|
10
|
-
|
|
11
|
-
services:
|
|
12
|
-
langfuse-server:
|
|
13
|
-
image: langfuse/langfuse:2
|
|
14
|
-
container_name: construct-langfuse
|
|
15
|
-
restart: unless-stopped
|
|
16
|
-
depends_on:
|
|
17
|
-
langfuse-db:
|
|
18
|
-
condition: service_healthy
|
|
19
|
-
ports:
|
|
20
|
-
- "3000:3000"
|
|
21
|
-
environment:
|
|
22
|
-
DATABASE_URL: postgresql://langfuse:langfuse@langfuse-db:5432/langfuse
|
|
23
|
-
NEXTAUTH_SECRET: ${LANGFUSE_NEXTAUTH_SECRET:-construct-nextauth-secret}
|
|
24
|
-
SALT: ${LANGFUSE_SALT:-construct-salt-value}
|
|
25
|
-
NEXTAUTH_URL: http://localhost:3000
|
|
26
|
-
TELEMETRY_ENABLED: "false"
|
|
27
|
-
LANGFUSE_ENABLE_EXPERIMENTAL_FEATURES: "true"
|
|
28
|
-
AUTH_DISABLE_SIGNUP: "false"
|
|
29
|
-
# ── Auto-provisioning (no browser setup needed) ──────────────────
|
|
30
|
-
LANGFUSE_INIT_ORG_ID: "construct-org"
|
|
31
|
-
LANGFUSE_INIT_ORG_NAME: "Construct"
|
|
32
|
-
LANGFUSE_INIT_PROJECT_ID: "construct-project"
|
|
33
|
-
LANGFUSE_INIT_PROJECT_NAME: "Construct"
|
|
34
|
-
LANGFUSE_INIT_PROJECT_PUBLIC_KEY: "pk-lf-construct-local"
|
|
35
|
-
LANGFUSE_INIT_PROJECT_SECRET_KEY: "sk-lf-construct-local"
|
|
36
|
-
LANGFUSE_INIT_USER_EMAIL: "admin@construct.local"
|
|
37
|
-
LANGFUSE_INIT_USER_NAME: "Admin"
|
|
38
|
-
LANGFUSE_INIT_USER_PASSWORD: "construct-admin"
|
|
39
|
-
healthcheck:
|
|
40
|
-
test: ["CMD-SHELL", "curl -sf http://localhost:3000/api/public/health || exit 1"]
|
|
41
|
-
interval: 10s
|
|
42
|
-
timeout: 5s
|
|
43
|
-
retries: 10
|
|
44
|
-
start_period: 30s
|
|
45
|
-
|
|
46
|
-
langfuse-db:
|
|
47
|
-
image: postgres:15-alpine
|
|
48
|
-
container_name: construct-langfuse-db
|
|
49
|
-
restart: unless-stopped
|
|
50
|
-
environment:
|
|
51
|
-
POSTGRES_USER: langfuse
|
|
52
|
-
POSTGRES_PASSWORD: langfuse
|
|
53
|
-
POSTGRES_DB: langfuse
|
|
54
|
-
volumes:
|
|
55
|
-
- langfuse_db_data:/var/lib/postgresql/data
|
|
56
|
-
healthcheck:
|
|
57
|
-
test: ["CMD-SHELL", "pg_isready -U langfuse -d langfuse"]
|
|
58
|
-
interval: 3s
|
|
59
|
-
timeout: 3s
|
|
60
|
-
retries: 10
|
|
61
|
-
|
|
62
|
-
dspy-optimizer:
|
|
63
|
-
build:
|
|
64
|
-
context: ./dspy-optimizer
|
|
65
|
-
dockerfile: Dockerfile
|
|
66
|
-
container_name: construct-dspy-optimizer
|
|
67
|
-
restart: "no"
|
|
68
|
-
profiles:
|
|
69
|
-
- optimize
|
|
70
|
-
env_file:
|
|
71
|
-
- ../.env
|
|
72
|
-
environment:
|
|
73
|
-
LANGFUSE_BASEURL: http://langfuse-server:3000
|
|
74
|
-
depends_on:
|
|
75
|
-
langfuse-server:
|
|
76
|
-
condition: service_healthy
|
|
77
|
-
volumes:
|
|
78
|
-
- ../.cx:/app/.cx
|
|
79
|
-
|
|
80
|
-
volumes:
|
|
81
|
-
langfuse_db_data:
|
|
82
|
-
driver: local
|
package/lib/eval-harness.mjs
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* lib/eval-harness.mjs — <one-line purpose>
|
|
4
|
-
*
|
|
5
|
-
* <2–6 line summary.>
|
|
6
|
-
*/
|
|
7
|
-
import fs from "node:fs";
|
|
8
|
-
import path from "node:path";
|
|
9
|
-
import { fileURLToPath } from "node:url";
|
|
10
|
-
|
|
11
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
12
|
-
const root = path.join(__dirname, "..");
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Basic evaluation harness for Construct agents.
|
|
16
|
-
* This script runs "dry runs" or simulated interactions against agent prompts
|
|
17
|
-
* to verify they would call the right tools or produce the right outcomes.
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
export async function runEval(agentName, input, expectedPatterns = []) {
|
|
21
|
-
const registry = JSON.parse(fs.readFileSync(path.join(root, "agents", "registry.json"), "utf8"));
|
|
22
|
-
const agent = registry.agents.find(a => a.name === agentName) ||
|
|
23
|
-
registry.personas.find(p => p.name === agentName);
|
|
24
|
-
|
|
25
|
-
if (!agent) throw new Error(`Agent ${agentName} not found in registry`);
|
|
26
|
-
|
|
27
|
-
// In a real production setup, this would call the LLM.
|
|
28
|
-
// For this harness, we are checking the "Static Intent" —
|
|
29
|
-
// can the agent logically fulfill the request based on its prompt?
|
|
30
|
-
|
|
31
|
-
const results = {
|
|
32
|
-
agent: agentName,
|
|
33
|
-
input,
|
|
34
|
-
passed: true,
|
|
35
|
-
findings: []
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
for (const pattern of expectedPatterns) {
|
|
39
|
-
const regex = new RegExp(pattern, "i");
|
|
40
|
-
const foundInPrompt = regex.test(agent.prompt || "");
|
|
41
|
-
const foundInShared = (registry.sharedGuidance || []).some(g => regex.test(g));
|
|
42
|
-
|
|
43
|
-
if (!foundInPrompt && !foundInShared) {
|
|
44
|
-
results.passed = false;
|
|
45
|
-
results.findings.push(`MISSING: Pattern "${pattern}" not supported by agent prompt or shared guidance`);
|
|
46
|
-
} else {
|
|
47
|
-
results.findings.push(`OK: Pattern "${pattern}" is supported`);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return results;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (process.argv[1] && import.meta.url === `file://${process.argv[1]}`) {
|
|
55
|
-
// Simple example run
|
|
56
|
-
const testAgent = process.argv[2] || "engineer";
|
|
57
|
-
const result = await runEval(testAgent, "Fix the bug", ["Edit", "Read", "Bash"]);
|
|
58
|
-
console.log(JSON.stringify(result, null, 2));
|
|
59
|
-
}
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* lib/hooks/bootstrap-guard.mjs — enforce start-of-session bootstrap trio.
|
|
4
|
-
*
|
|
5
|
-
* Blocks Write/Edit/MultiEdit/NotebookEdit/TodoWrite and destructive Bash
|
|
6
|
-
* until the session has invoked workflow_status + project_context + memory_search
|
|
7
|
-
* (or accumulated 3+ read-style tool calls, the equivalent signal that the
|
|
8
|
-
* agent has grounded itself before acting).
|
|
9
|
-
*/
|
|
10
|
-
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
|
|
11
|
-
import { join } from 'path';
|
|
12
|
-
import { homedir } from 'os';
|
|
13
|
-
|
|
14
|
-
let payload = {};
|
|
15
|
-
try { payload = JSON.parse(readFileSync(0, 'utf8')) || {}; } catch { process.exit(0); }
|
|
16
|
-
|
|
17
|
-
const sessionId = payload.session_id || payload.sessionId || 'default';
|
|
18
|
-
const toolName = payload.tool_name || payload.tool || '';
|
|
19
|
-
const toolInput = payload.tool_input || payload.toolInput || {};
|
|
20
|
-
|
|
21
|
-
const BOOTSTRAP_TOOLS = new Set([
|
|
22
|
-
'mcp__construct-mcp__workflow_status',
|
|
23
|
-
'mcp__construct-mcp__project_context',
|
|
24
|
-
'mcp__construct-mcp__memory_search',
|
|
25
|
-
'mcp__cass__memory_search',
|
|
26
|
-
'workflow_status', 'project_context', 'memory_search',
|
|
27
|
-
]);
|
|
28
|
-
const READ_TOOLS = new Set(['Read', 'Grep', 'Glob', 'LS', 'NotebookRead']);
|
|
29
|
-
const BLOCKED_TOOLS = new Set(['Write', 'Edit', 'MultiEdit', 'NotebookEdit', 'TodoWrite']);
|
|
30
|
-
const COMPATIBLE_TOOLS = new Set(['Read', 'Grep', 'Glob', 'LS', 'NotebookRead']);
|
|
31
|
-
|
|
32
|
-
const BENIGN_BASH = /^(git (status|log|diff|branch|show|rev-parse)|ls|cat|head|tail|pwd|wc|file|echo|which|node --version|npm --version)\b/;
|
|
33
|
-
|
|
34
|
-
const stateDir = join(homedir(), '.cx');
|
|
35
|
-
const statePath = join(stateDir, 'bootstrap-state.json');
|
|
36
|
-
|
|
37
|
-
let state = {};
|
|
38
|
-
if (existsSync(statePath)) {
|
|
39
|
-
try { state = JSON.parse(readFileSync(statePath, 'utf8')) || {}; } catch { state = {}; }
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const now = Date.now();
|
|
43
|
-
for (const [k, v] of Object.entries(state)) {
|
|
44
|
-
if (!v?.ts || now - v.ts > 24 * 60 * 60 * 1000) delete state[k];
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const s = state[sessionId] || { ts: now, reads: 0, bootstrap: new Set(), done: false };
|
|
48
|
-
if (Array.isArray(s.bootstrap)) s.bootstrap = new Set(s.bootstrap);
|
|
49
|
-
else if (!(s.bootstrap instanceof Set)) s.bootstrap = new Set();
|
|
50
|
-
s.ts = now;
|
|
51
|
-
|
|
52
|
-
if (BOOTSTRAP_TOOLS.has(toolName)) s.bootstrap.add(toolName.replace(/^.*__/, ''));
|
|
53
|
-
if (READ_TOOLS.has(toolName)) s.reads = (s.reads || 0) + 1;
|
|
54
|
-
|
|
55
|
-
if (!s.done) {
|
|
56
|
-
const hasTrio = s.bootstrap.has('workflow_status') && s.bootstrap.has('project_context') && s.bootstrap.has('memory_search');
|
|
57
|
-
if (hasTrio || (s.reads || 0) >= 3) s.done = true;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (!s.done && toolName && COMPATIBLE_TOOLS.has(toolName) && (s.reads || 0) >= 2) {
|
|
61
|
-
s.done = true;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
let block = false;
|
|
65
|
-
let reason = '';
|
|
66
|
-
if (!s.done) {
|
|
67
|
-
if (BLOCKED_TOOLS.has(toolName)) {
|
|
68
|
-
block = true;
|
|
69
|
-
reason = `${toolName} requires session bootstrap.`;
|
|
70
|
-
} else if (toolName === 'Bash') {
|
|
71
|
-
const cmd = (toolInput.command || '').trim();
|
|
72
|
-
if (cmd && !BENIGN_BASH.test(cmd)) { block = true; reason = 'Bash mutations require session bootstrap.'; }
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
try {
|
|
77
|
-
mkdirSync(stateDir, { recursive: true });
|
|
78
|
-
state[sessionId] = { ...s, bootstrap: Array.from(s.bootstrap) };
|
|
79
|
-
writeFileSync(statePath, JSON.stringify(state));
|
|
80
|
-
} catch { /* best effort */ }
|
|
81
|
-
|
|
82
|
-
if (block) {
|
|
83
|
-
process.stderr.write(
|
|
84
|
-
`[bootstrap-guard] ${reason}\n` +
|
|
85
|
-
`Run in parallel first: workflow_status, project_context, memory_search.\n` +
|
|
86
|
-
`(Or do 3+ exploratory reads — Read/Grep/Glob/LS — if this is a pure exploration task.)\n`
|
|
87
|
-
);
|
|
88
|
-
process.exit(2);
|
|
89
|
-
}
|
|
90
|
-
process.exit(0);
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* lib/hooks/console-warn.mjs — Console warn hook — warns when console.log/debug statements are left in code.
|
|
4
|
-
*
|
|
5
|
-
* Runs as PostToolUse after Edit/Write. Detects console.log and console.debug statements in edited files and emits a warning. Does not block — informational only.
|
|
6
|
-
*/
|
|
7
|
-
import { readFileSync, appendFileSync, existsSync } from 'fs';
|
|
8
|
-
import { homedir } from 'os';
|
|
9
|
-
import { basename } from 'path';
|
|
10
|
-
|
|
11
|
-
const CODE_EXTS = new Set(['.js','.mjs','.cjs','.ts','.tsx','.jsx']);
|
|
12
|
-
const filePath = process.env.TOOL_INPUT_FILE_PATH || '';
|
|
13
|
-
|
|
14
|
-
if (!filePath) process.exit(0);
|
|
15
|
-
|
|
16
|
-
const ext = '.' + filePath.split('.').pop();
|
|
17
|
-
if (!CODE_EXTS.has(ext)) process.exit(0);
|
|
18
|
-
|
|
19
|
-
if (!existsSync(filePath)) process.exit(0);
|
|
20
|
-
|
|
21
|
-
const lines = readFileSync(filePath, 'utf8').split('\n');
|
|
22
|
-
const hits = [];
|
|
23
|
-
|
|
24
|
-
for (let i = 0; i < lines.length; i++) {
|
|
25
|
-
const line = lines[i];
|
|
26
|
-
const stripped = line.replace(/\/\/.*$/, '').replace(/\/\*.*?\*\//g, '');
|
|
27
|
-
if (/\bconsole\.(log|warn|error|info|debug)\s*\(/.test(stripped) || /\bdebugger\s*;/.test(stripped)) {
|
|
28
|
-
hits.push(i + 1);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (hits.length === 0) process.exit(0);
|
|
33
|
-
|
|
34
|
-
const file = basename(filePath);
|
|
35
|
-
const lineList = hits.slice(0, 5).join(', ') + (hits.length > 5 ? '…' : '');
|
|
36
|
-
const msg = `Heads up: debug statements left in ${file} — console.log on line${hits.length > 1 ? 's' : ''} ${lineList}. Remove before shipping.`;
|
|
37
|
-
|
|
38
|
-
process.stderr.write(`[console-warn] ${msg}\n`);
|
|
39
|
-
|
|
40
|
-
const flagsPath = `${homedir()}/.cx/warn-flags.txt`;
|
|
41
|
-
try { appendFileSync(flagsPath, `console.log in ${file} (lines ${lineList})\n`); } catch { /* best effort */ }
|
|
42
|
-
|
|
43
|
-
process.exit(0);
|