@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,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lib/cache-strategy.js — Model-agnostic cache strategy layer.
|
|
3
|
+
*
|
|
4
|
+
* Follows embeddings-engine.js pattern:
|
|
5
|
+
* - This file is the model-agnostic router.
|
|
6
|
+
* - Provider-specific logic lives in cache-strategy-*.js adapters.
|
|
7
|
+
* - All adapters return the same annotation shape.
|
|
8
|
+
*
|
|
9
|
+
* Consumes provider capabilities from provider-capabilities.js.
|
|
10
|
+
* Emits provider-specific annotations for the dispatch layer.
|
|
11
|
+
*
|
|
12
|
+
* Standard annotation interface (all adapters return this shape):
|
|
13
|
+
* - messages: array (annotated message array ready for LLM API)
|
|
14
|
+
* - annotations: array (provider-specific annotation metadata)
|
|
15
|
+
* - expectedCacheWriteTokens: number | null
|
|
16
|
+
* - expectedCacheReadTokens: number | null
|
|
17
|
+
*/
|
|
18
|
+
import { resolveProviderCapabilities } from './provider-capabilities.js';
|
|
19
|
+
import { estimateTokens } from './token-engine.js';
|
|
20
|
+
|
|
21
|
+
const ADAPTERS = {
|
|
22
|
+
anthropic: () => import('./cache-strategy-anthropic.js'),
|
|
23
|
+
google: () => import('./cache-strategy-google.js'),
|
|
24
|
+
openai: () => import('./cache-strategy-openai.js'),
|
|
25
|
+
none: () => import('./cache-strategy-none.js'),
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
function resolveAdapterKey(caps) {
|
|
29
|
+
const format = caps?.annotationFormat || 'none';
|
|
30
|
+
if (ADAPTERS[format]) return format;
|
|
31
|
+
return 'none';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Annotate a prompt structure with provider-specific cache annotations.
|
|
36
|
+
*
|
|
37
|
+
* @param {object} promptStructure - { system, messages, staticEndIndex, totalTokens }
|
|
38
|
+
* @param {string} modelId
|
|
39
|
+
* @returns {Promise<object>} - { messages, annotations, expectedCacheWriteTokens }
|
|
40
|
+
*/
|
|
41
|
+
export async function annotatePrompt(promptStructure, modelId) {
|
|
42
|
+
const caps = await resolveProviderCapabilities(modelId);
|
|
43
|
+
const adapterKey = resolveAdapterKey(caps);
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
const { annotate } = await ADAPTERS[adapterKey]();
|
|
47
|
+
return await annotate(promptStructure, caps);
|
|
48
|
+
} catch {
|
|
49
|
+
// Fallback to none
|
|
50
|
+
const { annotate } = await ADAPTERS.none();
|
|
51
|
+
return await annotate(promptStructure, caps);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Estimate how many tokens should be cacheable from a prompt structure.
|
|
57
|
+
*
|
|
58
|
+
* @param {object} fragments - prompt fragments array
|
|
59
|
+
* @param {number} staticEndIndex - last index that is cacheable
|
|
60
|
+
* @param {object} opts - { modelId }
|
|
61
|
+
* @returns {Promise<number>}
|
|
62
|
+
*/
|
|
63
|
+
export async function estimateCacheableTokens(fragments, staticEndIndex, { modelId = '' } = {}) {
|
|
64
|
+
if (!Array.isArray(fragments) || staticEndIndex < 0) return 0;
|
|
65
|
+
|
|
66
|
+
let total = 0;
|
|
67
|
+
const endIdx = Math.min(staticEndIndex + 1, fragments.length);
|
|
68
|
+
|
|
69
|
+
for (let i = 0; i < endIdx; i++) {
|
|
70
|
+
const frag = fragments[i];
|
|
71
|
+
if (frag && frag.content) {
|
|
72
|
+
total += await estimateTokens(frag.content, { modelId });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return total;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Resolve cache TTL in tokens (not ms) for a given provider.
|
|
81
|
+
*
|
|
82
|
+
* @param {string} modelId
|
|
83
|
+
* @returns {Promise<{ ttl5m: number, ttl1h: number }>}
|
|
84
|
+
*/
|
|
85
|
+
export async function resolveCacheTTL(modelId) {
|
|
86
|
+
const caps = await resolveProviderCapabilities(modelId);
|
|
87
|
+
return {
|
|
88
|
+
ttl5m: caps?.cacheTTL?.['5m'] || 0,
|
|
89
|
+
ttl1h: caps?.cacheTTL?.['1h'] || 0,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lib/claude-allow.mjs — read / mutate / audit ~/.claude/settings.json permissions.allow.
|
|
3
|
+
*
|
|
4
|
+
* Claude Code's auto-classifier denies tool calls the user hasn't pre-authorized
|
|
5
|
+
* via `permissions.allow`. Editing that file from within Claude Code is blocked
|
|
6
|
+
* (self-modification of the agent's own permissions). This module is the
|
|
7
|
+
* outside path: Construct's CLI + SessionStart hook use it to surface gaps,
|
|
8
|
+
* propose entries, and apply them atomically.
|
|
9
|
+
*
|
|
10
|
+
* Gap detection is heuristic, not authoritative. We look at recent git
|
|
11
|
+
* branch names and suggest force-push allowlist entries for prefixes the user
|
|
12
|
+
* actually uses but hasn't allowlisted. That's the single biggest source of
|
|
13
|
+
* classifier friction; broader heuristics would be guess-work.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';
|
|
17
|
+
import { execSync } from 'node:child_process';
|
|
18
|
+
import { join, dirname } from 'node:path';
|
|
19
|
+
import { homedir } from 'node:os';
|
|
20
|
+
|
|
21
|
+
const DEFAULT_SETTINGS_PATH = join(homedir(), '.claude', 'settings.json');
|
|
22
|
+
|
|
23
|
+
const SAFE_PREFIXES = ['feat', 'fix', 'chore', 'docs', 'refactor', 'perf', 'cleanup', 'test', 'build', 'ci', 'style'];
|
|
24
|
+
const NEVER_PREFIXES = ['claude', 'agent', 'main', 'master', 'dev'];
|
|
25
|
+
|
|
26
|
+
function readSettings(path = DEFAULT_SETTINGS_PATH) {
|
|
27
|
+
if (!existsSync(path)) return { exists: false, settings: {}, path };
|
|
28
|
+
try {
|
|
29
|
+
return { exists: true, settings: JSON.parse(readFileSync(path, 'utf8')), path };
|
|
30
|
+
} catch (err) {
|
|
31
|
+
return { exists: true, settings: {}, path, parseError: err.message };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function writeSettings(settings, path = DEFAULT_SETTINGS_PATH) {
|
|
36
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
37
|
+
const text = `${JSON.stringify(settings, null, 2)}\n`;
|
|
38
|
+
writeFileSync(path, text, 'utf8');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function listAllowEntries({ path = DEFAULT_SETTINGS_PATH } = {}) {
|
|
42
|
+
const { settings } = readSettings(path);
|
|
43
|
+
return Array.isArray(settings?.permissions?.allow) ? [...settings.permissions.allow] : [];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Add one or more allowlist patterns. Idempotent — duplicates are dropped.
|
|
48
|
+
* Returns { added: string[], existing: string[], total: number }.
|
|
49
|
+
*/
|
|
50
|
+
export function addAllowEntries(entries, { path = DEFAULT_SETTINGS_PATH } = {}) {
|
|
51
|
+
const incoming = (Array.isArray(entries) ? entries : [entries]).filter((e) => typeof e === 'string' && e.trim());
|
|
52
|
+
const { settings } = readSettings(path);
|
|
53
|
+
if (!settings.permissions) settings.permissions = {};
|
|
54
|
+
if (!Array.isArray(settings.permissions.allow)) settings.permissions.allow = [];
|
|
55
|
+
|
|
56
|
+
const existingSet = new Set(settings.permissions.allow);
|
|
57
|
+
const added = [];
|
|
58
|
+
const existing = [];
|
|
59
|
+
for (const entry of incoming) {
|
|
60
|
+
if (existingSet.has(entry)) existing.push(entry);
|
|
61
|
+
else { settings.permissions.allow.push(entry); existingSet.add(entry); added.push(entry); }
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (added.length > 0) writeSettings(settings, path);
|
|
65
|
+
return { added, existing, total: settings.permissions.allow.length, path };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Remove patterns. Returns { removed: string[], notFound: string[], total }.
|
|
70
|
+
*/
|
|
71
|
+
export function removeAllowEntries(entries, { path = DEFAULT_SETTINGS_PATH } = {}) {
|
|
72
|
+
const incoming = (Array.isArray(entries) ? entries : [entries]).filter((e) => typeof e === 'string' && e.trim());
|
|
73
|
+
const { settings } = readSettings(path);
|
|
74
|
+
if (!Array.isArray(settings?.permissions?.allow)) return { removed: [], notFound: incoming, total: 0, path };
|
|
75
|
+
|
|
76
|
+
const current = new Set(settings.permissions.allow);
|
|
77
|
+
const removed = [];
|
|
78
|
+
const notFound = [];
|
|
79
|
+
for (const entry of incoming) {
|
|
80
|
+
if (current.has(entry)) { current.delete(entry); removed.push(entry); }
|
|
81
|
+
else notFound.push(entry);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (removed.length > 0) {
|
|
85
|
+
settings.permissions.allow = Array.from(current);
|
|
86
|
+
writeSettings(settings, path);
|
|
87
|
+
}
|
|
88
|
+
return { removed, notFound, total: settings.permissions.allow.length, path };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Scan recent local branches for prefix patterns the user actually uses.
|
|
93
|
+
* Returns the distinct safe prefixes present in the working tree, excluding
|
|
94
|
+
* NEVER_PREFIXES (main/master/dev/claude/agent).
|
|
95
|
+
*/
|
|
96
|
+
export function detectBranchPrefixes({ cwd = process.cwd(), limit = 200 } = {}) {
|
|
97
|
+
try {
|
|
98
|
+
const out = execSync(`git for-each-ref --count=${limit} --sort=-committerdate --format='%(refname:short)' refs/heads/`, {
|
|
99
|
+
cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'],
|
|
100
|
+
});
|
|
101
|
+
const branches = out.split('\n').map((s) => s.trim().replace(/^'|'$/g, '')).filter(Boolean);
|
|
102
|
+
const prefixes = new Set();
|
|
103
|
+
for (const b of branches) {
|
|
104
|
+
const idx = b.indexOf('/');
|
|
105
|
+
if (idx <= 0) continue;
|
|
106
|
+
const prefix = b.slice(0, idx);
|
|
107
|
+
if (NEVER_PREFIXES.includes(prefix)) continue;
|
|
108
|
+
if (!SAFE_PREFIXES.includes(prefix)) continue;
|
|
109
|
+
prefixes.add(prefix);
|
|
110
|
+
}
|
|
111
|
+
return Array.from(prefixes).sort();
|
|
112
|
+
} catch { return []; }
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Compare branch prefixes against existing allowlist; return entries the user
|
|
117
|
+
* almost certainly wants but hasn't added. Conservative — only force-push
|
|
118
|
+
* entries, only for prefixes that are SAFE.
|
|
119
|
+
*/
|
|
120
|
+
export function detectAllowlistGaps({ cwd = process.cwd(), path = DEFAULT_SETTINGS_PATH } = {}) {
|
|
121
|
+
const allow = listAllowEntries({ path });
|
|
122
|
+
const have = new Set(allow);
|
|
123
|
+
const prefixes = detectBranchPrefixes({ cwd });
|
|
124
|
+
const gaps = [];
|
|
125
|
+
for (const prefix of prefixes) {
|
|
126
|
+
const pattern = `Bash(git push --force-with-lease origin ${prefix}/*)`;
|
|
127
|
+
if (!have.has(pattern)) gaps.push({ prefix, pattern });
|
|
128
|
+
}
|
|
129
|
+
return gaps;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* One-line posture string for SessionStart injection. Keeps the surface small:
|
|
134
|
+
* count of current entries + at most 3 suggested gaps. Empty string when
|
|
135
|
+
* nothing to surface so the SessionStart banner stays clean.
|
|
136
|
+
*/
|
|
137
|
+
export function buildPermissionPostureLine({ cwd = process.cwd(), path = DEFAULT_SETTINGS_PATH } = {}) {
|
|
138
|
+
const allow = listAllowEntries({ path });
|
|
139
|
+
const gaps = detectAllowlistGaps({ cwd, path });
|
|
140
|
+
if (gaps.length === 0) return '';
|
|
141
|
+
const sample = gaps.slice(0, 3).map((g) => g.prefix).join(', ');
|
|
142
|
+
const more = gaps.length > 3 ? ` (+${gaps.length - 3} more)` : '';
|
|
143
|
+
return (
|
|
144
|
+
`\n## Permission posture\n` +
|
|
145
|
+
`Allowlist: ${allow.length} entr${allow.length === 1 ? 'y' : 'ies'} in ${path}.\n` +
|
|
146
|
+
`Suggested gaps: force-push allowlist missing for ${sample}${more}. ` +
|
|
147
|
+
`Close via \`construct claude:allow check --apply\`.\n`
|
|
148
|
+
);
|
|
149
|
+
}
|