@geraldmaron/construct 1.0.20 → 1.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -5
- package/bin/construct +194 -16
- package/bin/construct-postinstall.mjs +25 -15
- package/lib/acp/server.mjs +113 -0
- package/lib/agent-instructions/inject.mjs +94 -0
- package/lib/auto-docs.mjs +10 -2
- package/lib/cli-commands.mjs +44 -16
- package/lib/comment-lint.mjs +115 -0
- package/lib/completions.mjs +7 -1
- package/lib/config/schema.mjs +22 -0
- package/lib/decisions/enforced-baseline.json +3 -0
- package/lib/docs-verify.mjs +15 -18
- package/lib/doctor/cli.mjs +8 -1
- package/lib/document-export.mjs +124 -0
- package/lib/document-ingest.mjs +13 -4
- package/lib/embed/daemon.mjs +1 -1
- package/lib/embed/inbox.mjs +25 -7
- package/lib/embedded-contract/triage.mjs +24 -2
- package/lib/embedded-contract/workflow-invoke.mjs +21 -0
- package/lib/features.mjs +11 -11
- package/lib/git-hooks-path.mjs +61 -0
- package/lib/home-namespace.mjs +60 -0
- package/lib/hooks/ci-status-check.mjs +62 -40
- package/lib/hooks/orchestration-dispatch-guard.mjs +153 -0
- package/lib/hooks/pre-push-gate.mjs +15 -6
- package/lib/hooks/stop-notify.mjs +32 -17
- package/lib/hooks/stop-typecheck.mjs +7 -2
- package/lib/host-capabilities.mjs +24 -8
- package/lib/host-disposition.mjs +76 -0
- package/lib/ingest/provider-extract.mjs +1 -1
- package/lib/ingest/strategy.mjs +35 -3
- package/lib/init-docs.mjs +1 -1
- package/lib/init-unified.mjs +320 -219
- package/lib/init-update.mjs +4 -84
- package/lib/init.mjs +9 -25
- package/lib/install/stage-project.mjs +8 -2
- package/lib/intent-classifier.mjs +1 -1
- package/lib/knowledge/search.mjs +52 -3
- package/lib/mcp/server.mjs +57 -14
- package/lib/mcp/tools/memory.mjs +2 -2
- package/lib/mcp/tools/orchestration-run.mjs +125 -0
- package/lib/model-registry.mjs +40 -33
- package/lib/observation-store.mjs +6 -2
- package/lib/opencode-config.mjs +1 -1
- package/lib/orchestration/events.mjs +66 -0
- package/lib/orchestration/run-store-postgres.mjs +85 -0
- package/lib/orchestration/run-store-sqlite.mjs +122 -0
- package/lib/orchestration/runtime.mjs +188 -50
- package/lib/orchestration/store.mjs +102 -0
- package/lib/orchestration/worker.mjs +215 -0
- package/lib/orchestration-policy.mjs +27 -3
- package/lib/parity.mjs +80 -26
- package/lib/policy/unified-gates.mjs +96 -0
- package/lib/project-init-shared.mjs +0 -173
- package/lib/reconcile/adapter-prune.mjs +105 -0
- package/lib/reconcile/agent-instructions-rewrap.mjs +98 -0
- package/lib/reconcile/gitignore-coverage.mjs +88 -0
- package/lib/reconcile/index.mjs +171 -0
- package/lib/reconcile/legacy-doctrine-strip.mjs +139 -0
- package/lib/reconcile/legacy-guide-decommit.mjs +67 -0
- package/lib/reconcile/legacy-skills-cleanup.mjs +200 -0
- package/lib/reconcile/mcp-entry-reconcile.mjs +142 -0
- package/lib/reconcile/postgres-namespace.mjs +102 -0
- package/lib/runtime/uv-bootstrap.mjs +27 -3
- package/lib/schema-infer.mjs +16 -2
- package/lib/server/csrf.mjs +14 -2
- package/lib/server/index.mjs +95 -0
- package/lib/service-manager.mjs +39 -14
- package/lib/setup-prompts.mjs +2 -1
- package/lib/setup.mjs +165 -141
- package/lib/storage/backend.mjs +14 -0
- package/lib/storage/unified-storage.mjs +550 -0
- package/lib/template-registry.mjs +73 -0
- package/lib/term-format.mjs +75 -0
- package/lib/uninstall/uninstall.mjs +180 -7
- package/package.json +2 -2
- package/personas/construct.md +7 -8
- package/platforms/claude/settings.template.json +30 -4
- package/platforms/opencode/config.template.json +2 -2
- package/rules/common/neurodivergent-output.md +66 -0
- package/rules/common/tool-invisibility.md +37 -0
- package/scripts/sync-specialists.mjs +381 -95
- package/skills/operating/orchestration-reference.md +2 -16
- package/specialists/policy-inventory.json +14 -0
- package/specialists/prompts/cx-accessibility.md +2 -6
- package/specialists/prompts/cx-ai-engineer.md +0 -4
- package/specialists/prompts/cx-architect.md +3 -5
- package/specialists/prompts/cx-business-strategist.md +0 -5
- package/specialists/prompts/cx-data-analyst.md +0 -4
- package/specialists/prompts/cx-data-engineer.md +0 -4
- package/specialists/prompts/cx-debugger.md +2 -6
- package/specialists/prompts/cx-designer.md +0 -8
- package/specialists/prompts/cx-devil-advocate.md +2 -2
- package/specialists/prompts/cx-docs-keeper.md +0 -13
- package/specialists/prompts/cx-engineer.md +0 -13
- package/specialists/prompts/cx-evaluator.md +2 -2
- package/specialists/prompts/cx-explorer.md +4 -5
- package/specialists/prompts/cx-legal-compliance.md +4 -5
- package/specialists/prompts/cx-operations.md +0 -5
- package/specialists/prompts/cx-orchestrator.md +0 -4
- package/specialists/prompts/cx-platform-engineer.md +0 -8
- package/specialists/prompts/cx-product-manager.md +0 -8
- package/specialists/prompts/cx-qa.md +2 -11
- package/specialists/prompts/cx-rd-lead.md +0 -5
- package/specialists/prompts/cx-release-manager.md +0 -8
- package/specialists/prompts/cx-researcher.md +5 -29
- package/specialists/prompts/cx-reviewer.md +2 -6
- package/specialists/prompts/cx-security.md +2 -11
- package/specialists/prompts/cx-sre.md +0 -15
- package/specialists/prompts/cx-test-automation.md +0 -4
- package/specialists/prompts/cx-trace-reviewer.md +2 -2
- package/specialists/prompts/cx-ux-researcher.md +0 -4
- package/specialists/registry.json +29 -29
- package/templates/distribution/run.mjs +36 -7
- package/templates/docs/accessibility-audit.md +56 -0
- package/templates/docs/architecture-review.md +59 -0
- package/templates/docs/code-review-report.md +46 -0
- package/templates/docs/construct_guide.md +14 -14
- package/templates/docs/debug-investigation.md +53 -0
- package/templates/docs/qa-report.md +48 -0
- package/templates/docs/security-audit-report.md +48 -0
- package/templates/docs/task-packet.md +49 -0
- package/templates/docs/verdict.md +40 -0
- package/lib/server/static/index.html +0 -1
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
"permissions": {
|
|
13
13
|
"edit": "allow",
|
|
14
14
|
"bash": "allow",
|
|
15
|
-
"webfetch": "allow"
|
|
15
|
+
"webfetch": "allow",
|
|
16
|
+
"websearch": "allow"
|
|
16
17
|
},
|
|
17
18
|
"claudeTools": "Read,Grep,Glob,LS,Edit,Write,Bash,WebSearch,WebFetch,summarize_diff,scan_file,project_context,memory_create_entities,list_skills,get_skill,search_skills,list_teams,get_team,memory_search,memory_add_observations,cx_trace,cx_score",
|
|
18
19
|
"promptFile": "personas/construct.md",
|
|
@@ -417,7 +418,7 @@
|
|
|
417
418
|
"modelTier": "standard",
|
|
418
419
|
"reasoningEffort": "medium",
|
|
419
420
|
"codexSandbox": "read-only",
|
|
420
|
-
"claudeTools": "Read,Grep,Glob,LS,Bash,list_skills,get_skill,search_skills,memory_search,memory_add_observations,cx_trace,cx_score",
|
|
421
|
+
"claudeTools": "Read,Grep,Glob,LS,Bash,list_skills,get_skill,search_skills,memory_search,memory_add_observations,cx_trace,cx_score,get_template,list_templates",
|
|
421
422
|
"promptFile": "specialists/prompts/cx-evaluator.md",
|
|
422
423
|
"embedOrientation": {
|
|
423
424
|
"focusAreas": [
|
|
@@ -628,7 +629,7 @@
|
|
|
628
629
|
"modelTier": "reasoning",
|
|
629
630
|
"reasoningEffort": "high",
|
|
630
631
|
"codexSandbox": "read-only",
|
|
631
|
-
"claudeTools": "Read,Grep,Glob,LS,Bash,list_skills,get_skill,search_skills,memory_search,memory_add_observations",
|
|
632
|
+
"claudeTools": "Read,Grep,Glob,LS,Bash,list_skills,get_skill,search_skills,memory_search,memory_add_observations,get_template,list_templates",
|
|
632
633
|
"promptFile": "specialists/prompts/cx-devil-advocate.md",
|
|
633
634
|
"embedOrientation": {
|
|
634
635
|
"focusAreas": [
|
|
@@ -673,7 +674,7 @@
|
|
|
673
674
|
"modelTier": "reasoning",
|
|
674
675
|
"reasoningEffort": "high",
|
|
675
676
|
"codexSandbox": "read-only",
|
|
676
|
-
"claudeTools": "Read,Grep,Glob,LS,Bash,list_skills,get_skill,search_skills,memory_search,memory_add_observations,cx_trace,cx_score",
|
|
677
|
+
"claudeTools": "Read,Grep,Glob,LS,Bash,list_skills,get_skill,search_skills,memory_search,memory_add_observations,cx_trace,cx_score,get_template,list_templates",
|
|
677
678
|
"promptFile": "specialists/prompts/cx-reviewer.md",
|
|
678
679
|
"embedOrientation": {
|
|
679
680
|
"focusAreas": [
|
|
@@ -716,7 +717,7 @@
|
|
|
716
717
|
"modelTier": "reasoning",
|
|
717
718
|
"reasoningEffort": "high",
|
|
718
719
|
"codexSandbox": "read-only",
|
|
719
|
-
"claudeTools": "Read,Grep,Glob,LS,Bash,list_skills,get_skill,search_skills,memory_search,memory_add_observations,cx_trace,cx_score",
|
|
720
|
+
"claudeTools": "Read,Grep,Glob,LS,Bash,list_skills,get_skill,search_skills,memory_search,memory_add_observations,cx_trace,cx_score,get_template,list_templates",
|
|
720
721
|
"promptFile": "specialists/prompts/cx-security.md",
|
|
721
722
|
"embedOrientation": {
|
|
722
723
|
"focusAreas": [
|
|
@@ -776,7 +777,7 @@
|
|
|
776
777
|
"modelTier": "standard",
|
|
777
778
|
"reasoningEffort": "medium",
|
|
778
779
|
"codexSandbox": "workspace-write",
|
|
779
|
-
"claudeTools": "Read,Grep,Glob,LS,Edit,Write,Bash,list_skills,get_skill,search_skills,memory_search,memory_add_observations,cx_trace,cx_score",
|
|
780
|
+
"claudeTools": "Read,Grep,Glob,LS,Edit,Write,Bash,list_skills,get_skill,search_skills,memory_search,memory_add_observations,cx_trace,cx_score,get_template,list_templates",
|
|
780
781
|
"promptFile": "specialists/prompts/cx-qa.md",
|
|
781
782
|
"embedOrientation": {
|
|
782
783
|
"focusAreas": [
|
|
@@ -824,7 +825,7 @@
|
|
|
824
825
|
"modelTier": "reasoning",
|
|
825
826
|
"reasoningEffort": "high",
|
|
826
827
|
"codexSandbox": "workspace-write",
|
|
827
|
-
"claudeTools": "Read,Grep,Glob,LS,Bash,Edit,WebSearch,WebFetch,list_skills,get_skill,search_skills,memory_search,memory_add_observations,cx_trace,cx_score",
|
|
828
|
+
"claudeTools": "Read,Grep,Glob,LS,Bash,Edit,WebSearch,WebFetch,list_skills,get_skill,search_skills,memory_search,memory_add_observations,cx_trace,cx_score,get_template,list_templates",
|
|
828
829
|
"promptFile": "specialists/prompts/cx-debugger.md",
|
|
829
830
|
"embedOrientation": {
|
|
830
831
|
"focusAreas": [
|
|
@@ -987,7 +988,7 @@
|
|
|
987
988
|
"modelTier": "standard",
|
|
988
989
|
"reasoningEffort": "medium",
|
|
989
990
|
"codexSandbox": "read-only",
|
|
990
|
-
"claudeTools": "Read,Grep,Glob,LS,WebSearch,WebFetch,list_skills,get_skill,search_skills,memory_search,memory_add_observations",
|
|
991
|
+
"claudeTools": "Read,Grep,Glob,LS,WebSearch,WebFetch,list_skills,get_skill,search_skills,memory_search,memory_add_observations,get_template,list_templates",
|
|
991
992
|
"promptFile": "specialists/prompts/cx-legal-compliance.md",
|
|
992
993
|
"embedOrientation": {
|
|
993
994
|
"focusAreas": [
|
|
@@ -1179,7 +1180,7 @@
|
|
|
1179
1180
|
"modelTier": "standard",
|
|
1180
1181
|
"reasoningEffort": "medium",
|
|
1181
1182
|
"codexSandbox": "read-only",
|
|
1182
|
-
"claudeTools": "Read,Grep,Glob,LS,Bash,list_skills,get_skill,search_skills,memory_search,memory_add_observations",
|
|
1183
|
+
"claudeTools": "Read,Grep,Glob,LS,Bash,list_skills,get_skill,search_skills,memory_search,memory_add_observations,get_template,list_templates",
|
|
1183
1184
|
"promptFile": "specialists/prompts/cx-accessibility.md",
|
|
1184
1185
|
"embedOrientation": {
|
|
1185
1186
|
"focusAreas": [
|
|
@@ -1227,7 +1228,7 @@
|
|
|
1227
1228
|
"modelTier": "fast",
|
|
1228
1229
|
"reasoningEffort": "medium",
|
|
1229
1230
|
"codexSandbox": "read-only",
|
|
1230
|
-
"claudeTools": "Read,Grep,Glob,LS,Bash,list_skills,get_skill,search_skills,memory_search,memory_add_observations",
|
|
1231
|
+
"claudeTools": "Read,Grep,Glob,LS,Bash,list_skills,get_skill,search_skills,memory_search,memory_add_observations,get_template,list_templates",
|
|
1231
1232
|
"promptFile": "specialists/prompts/cx-explorer.md",
|
|
1232
1233
|
"embedOrientation": {
|
|
1233
1234
|
"focusAreas": [
|
|
@@ -1266,7 +1267,7 @@
|
|
|
1266
1267
|
"description": "Tracks fleet-level performance patterns — stable median scores can hide high-variance agents that are failing silently.",
|
|
1267
1268
|
"modelTier": "reasoning",
|
|
1268
1269
|
"reasoningEffort": "high",
|
|
1269
|
-
"claudeTools": "Read,Write,Bash,list_skills,get_skill,search_skills,memory_search,memory_add_observations,cx_trace,cx_score",
|
|
1270
|
+
"claudeTools": "Read,Write,Bash,list_skills,get_skill,search_skills,memory_search,memory_add_observations,cx_trace,cx_score,get_template,list_templates",
|
|
1270
1271
|
"promptFile": "specialists/prompts/cx-trace-reviewer.md",
|
|
1271
1272
|
"embedOrientation": {
|
|
1272
1273
|
"focusAreas": [
|
|
@@ -1427,8 +1428,8 @@
|
|
|
1427
1428
|
"options": {
|
|
1428
1429
|
"baseURL": "https://openrouter.ai/api/v1",
|
|
1429
1430
|
"headers": {
|
|
1430
|
-
"HTTP-Referer": "
|
|
1431
|
-
"X-Title": "
|
|
1431
|
+
"HTTP-Referer": "https://github.com/geraldmaron/construct",
|
|
1432
|
+
"X-Title": "Construct"
|
|
1432
1433
|
}
|
|
1433
1434
|
},
|
|
1434
1435
|
"models": {
|
|
@@ -1462,7 +1463,7 @@
|
|
|
1462
1463
|
"command": "npx",
|
|
1463
1464
|
"args": [
|
|
1464
1465
|
"-y",
|
|
1465
|
-
"@upstash/context7-mcp@
|
|
1466
|
+
"@upstash/context7-mcp@3.1.0"
|
|
1466
1467
|
],
|
|
1467
1468
|
"description": "Library and framework documentation lookup"
|
|
1468
1469
|
},
|
|
@@ -1470,7 +1471,7 @@
|
|
|
1470
1471
|
"command": "npx",
|
|
1471
1472
|
"args": [
|
|
1472
1473
|
"-y",
|
|
1473
|
-
"@playwright/mcp@
|
|
1474
|
+
"@playwright/mcp@0.0.75"
|
|
1474
1475
|
],
|
|
1475
1476
|
"description": "Browser automation and E2E testing"
|
|
1476
1477
|
},
|
|
@@ -1478,7 +1479,7 @@
|
|
|
1478
1479
|
"type": "url",
|
|
1479
1480
|
"url": "https://api.githubcopilot.com/mcp/",
|
|
1480
1481
|
"headers": {
|
|
1481
|
-
"Authorization": "Bearer
|
|
1482
|
+
"Authorization": "Bearer {env:GITHUB_TOKEN}"
|
|
1482
1483
|
},
|
|
1483
1484
|
"description": "GitHub API: issues, PRs, code search"
|
|
1484
1485
|
},
|
|
@@ -1486,7 +1487,7 @@
|
|
|
1486
1487
|
"command": "npx",
|
|
1487
1488
|
"args": [
|
|
1488
1489
|
"-y",
|
|
1489
|
-
"@modelcontextprotocol/server-sequential-thinking"
|
|
1490
|
+
"@modelcontextprotocol/server-sequential-thinking@2025.12.18"
|
|
1490
1491
|
],
|
|
1491
1492
|
"description": "Complex multi-step reasoning chains"
|
|
1492
1493
|
},
|
|
@@ -1500,17 +1501,18 @@
|
|
|
1500
1501
|
},
|
|
1501
1502
|
"sharedGuidance": [
|
|
1502
1503
|
"Session Resumption: start every new chat by grounding in project_context, memory_search, AGENTS.md, plan.md, and the relevant repo docs. Apply results silently — never ask the user to repeat information that memory already holds.",
|
|
1503
|
-
"Memory recording: after
|
|
1504
|
-
"Project Identification: identify the current project from the workspace
|
|
1505
|
-
"Loop guard: if
|
|
1504
|
+
"Memory recording: after meaningful work, call memory_add_observations to record patterns, decisions with rationale, anti-patterns, and open questions. Summaries must be specific and ≥30 characters — avoid placeholders.",
|
|
1505
|
+
"Project Identification: identify the current project from the workspace or memory MCP, and focus on that target repository.",
|
|
1506
|
+
"Loop guard: if the same command or tool call is attempted 3+ times with identical arguments and no state change, stop and surface what blocked progress and what decision is needed.",
|
|
1506
1507
|
"Circuit breaker: after 3 failed attempts at the same approach, stop all edits. Revert to last known working state. Document what was tried and escalate to the user with full context.",
|
|
1507
|
-
"Worker task contract: specialists return exactly one terminal state
|
|
1508
|
-
"Tool naming contract: use the exact tool names exposed by the current host
|
|
1509
|
-
"Observability: you MUST call cx_trace at the start of every new task
|
|
1510
|
-
"Quality scoring: after
|
|
1511
|
-
"Model failover:
|
|
1508
|
+
"Worker task contract: specialists return exactly one terminal state — DONE (files + verification), BLOCKED (blocker + attempts), or NEEDS_MAIN_INPUT (per the `construct-to-orchestrator` shape in specialists/contracts.json). Never interview the user from a child session.",
|
|
1509
|
+
"Tool naming contract: use the exact tool names exposed by the current host; never emit names from other vendors' catalogs. The bash tool requires both command and description string fields. Prefer rg over find/grep. If a needed tool is missing, use the closest available primitive.",
|
|
1510
|
+
"Observability: you MUST call cx_trace at the start of every new task with your agent name and the user goal. Construct attaches prompt provenance automatically. If the tool is unavailable, log and continue — telemetry must never block execution.",
|
|
1511
|
+
"Quality scoring: after a significant deliverable, you MUST call cx_score with `name=quality`, a 0.0–1.0 value, a brief comment, and the `trace_id` returned by cx_trace.",
|
|
1512
|
+
"Model failover: on rate-limit / quota / model-unavailability errors, the PostToolUseFailure hook may switch model assignments. Surface whether fallback ran; retry only after assignments changed.",
|
|
1512
1513
|
"Detailed orchestration reference (execution contract, handoff template, intent/category classification, parallel dispatch, horizontal routing, efficiency discipline) is in skills/operating/orchestration-reference.md — call get_skill(\"operating/orchestration-reference\") when you need it.",
|
|
1513
|
-
"Agent contracts:
|
|
1514
|
+
"Agent contracts: typed producer→consumer contracts live in `specialists/contracts.json`. Call the `agent_contract` MCP tool at handoff to fetch the current shape; `routeRequest` returns `contractChain` alongside `specialists`.",
|
|
1515
|
+
"Tool invisibility: a deliverable artifact is about the user's project, never about the tooling that produced it. In artifact content never name Construct, the `cx-*` specialist role ids, or internal orchestration mechanics (task-packets, orchestration_run, dispatch chains) — unless the subject project IS Construct itself. A metric owner is a real role on the user's team, never a `cx-*` id. Provenance goes in a comment or handoff, not the deliverable's prose. See rules/common/tool-invisibility.md."
|
|
1514
1516
|
],
|
|
1515
1517
|
"platformGuidance": {
|
|
1516
1518
|
"opencode": [
|
|
@@ -1519,9 +1521,7 @@
|
|
|
1519
1521
|
"OpenCode subagents are not primary chat surfaces. If you are running as a subagent and you need user input, do not prompt the user from the child session. Return a concise NEEDS_MAIN_INPUT packet containing the blocker, exact question, safe default, and current task/session context so the primary persona can ask the user and resume.",
|
|
1520
1522
|
"If a subagent returns NEEDS_MAIN_INPUT, the primary persona must ask the user in the main session, update the tracker or plan with the blocker, then resume or re-dispatch the specialist with the answer.",
|
|
1521
1523
|
"Provider fallback is not guaranteed inside OpenCode provider/session failures. If you see a provider quota or usage-limit error, run or ask the main session to run `construct models --apply` after confirming an OpenRouter key is available, then retry after sync changes model assignments.",
|
|
1522
|
-
"Use OpenCode's native plugin, agent, command, and hook surfaces as the orchestration substrate. Visible handoff blocks are fallback/debug artifacts, not the workflow itself."
|
|
1523
|
-
"Loop guard: if you observe the same command or tool call being attempted more than 3 times with identical arguments and no state change, stop immediately and surface what blocked progress.",
|
|
1524
|
-
"If the memory MCP is available, call search_nodes with the current project name before starting work to retrieve prior session context."
|
|
1524
|
+
"Use OpenCode's native plugin, agent, command, and hook surfaces as the orchestration substrate. Visible handoff blocks are fallback/debug artifacts, not the workflow itself."
|
|
1525
1525
|
],
|
|
1526
1526
|
"claude": [
|
|
1527
1527
|
"Follow workspace instructions, project-level CLAUDE.md, agent definitions in ~/.claude/specialists/, slash commands, and hooks. Project-level instructions override global ones.",
|
|
@@ -14,30 +14,38 @@
|
|
|
14
14
|
* and the launcher invokes its `bin/construct`. Used for development
|
|
15
15
|
* and smoke tests; not consulted in normal runs.
|
|
16
16
|
*
|
|
17
|
-
* 1.
|
|
17
|
+
* 1. Self-repo — if this launcher is staged inside the Construct source
|
|
18
|
+
* checkout itself (the project's own `package.json` is
|
|
19
|
+
* `@geraldmaron/construct` and `bin/construct` is present), invoke that
|
|
20
|
+
* `bin/construct` directly. Without this, the Construct repo's own hooks
|
|
21
|
+
* would dead-end at npx/global resolution and fail every session.
|
|
22
|
+
*
|
|
23
|
+
* 2. Workspace `node_modules/@geraldmaron/construct/bin/construct` — if a
|
|
18
24
|
* `npm install` has materialised Construct in this project's node_modules,
|
|
19
25
|
* use that. Fastest, no network.
|
|
20
26
|
*
|
|
21
|
-
*
|
|
27
|
+
* 3. `npx -p @geraldmaron/construct@<version> construct …` — if Node ≥ 18
|
|
22
28
|
* is on PATH but the package isn't installed locally. npx caches the
|
|
23
29
|
* package after the first run. The version pin comes from
|
|
24
|
-
* `.construct/version` next to this file.
|
|
30
|
+
* `.construct/version` next to this file. The pin is probed first; if it
|
|
31
|
+
* cannot be resolved (offline, or the version is unpublished/yanked) the
|
|
32
|
+
* launcher defers to the resolvers below instead of dead-ending here.
|
|
25
33
|
*
|
|
26
|
-
*
|
|
34
|
+
* 4. Globally installed `construct` on PATH — if neither of the above
|
|
27
35
|
* hit but the user has installed Construct globally.
|
|
28
36
|
*
|
|
29
|
-
*
|
|
37
|
+
* 5. Cached binary at `.construct/cache/bin/construct-<os>-<arch>` — if
|
|
30
38
|
* a previous bootstrap downloaded the matching single-file binary
|
|
31
39
|
* from GitHub Releases.
|
|
32
40
|
*
|
|
33
|
-
*
|
|
41
|
+
* 6. Docker container — if the docker daemon is reachable, invoke
|
|
34
42
|
* `ghcr.io/geraldmaron/construct:<pinned-version>` with the project
|
|
35
43
|
* bind-mounted at /work. Lets language-agnostic projects (no Node,
|
|
36
44
|
* no global construct, no binary) still execute hooks. Disable with
|
|
37
45
|
* `CONSTRUCT_DISABLE_DOCKER=1` for environments where docker is
|
|
38
46
|
* reachable but undesirable (e.g. CI runners that prefer fail-fast).
|
|
39
47
|
*
|
|
40
|
-
*
|
|
48
|
+
* 7. Print a precise error with the exact install commands and exit
|
|
41
49
|
* with the documented exit code (127 = command not found).
|
|
42
50
|
*
|
|
43
51
|
* The launcher is intentionally tiny and dependency-free so it never
|
|
@@ -99,6 +107,18 @@ function tryDevPath() {
|
|
|
99
107
|
return true;
|
|
100
108
|
}
|
|
101
109
|
|
|
110
|
+
function trySelfRepo() {
|
|
111
|
+
const candidate = join(PROJECT_ROOT, 'bin', 'construct');
|
|
112
|
+
if (!isExecutable(candidate)) return false;
|
|
113
|
+
let pkgName = null;
|
|
114
|
+
try {
|
|
115
|
+
pkgName = JSON.parse(readFileSync(join(PROJECT_ROOT, 'package.json'), 'utf8')).name;
|
|
116
|
+
} catch { return false; }
|
|
117
|
+
if (pkgName !== '@geraldmaron/construct') return false;
|
|
118
|
+
runForeground(process.execPath, [candidate, ...process.argv.slice(2)]);
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
|
|
102
122
|
function tryNodeModules() {
|
|
103
123
|
const candidate = join(
|
|
104
124
|
PROJECT_ROOT,
|
|
@@ -112,6 +132,14 @@ function tryNodeModules() {
|
|
|
112
132
|
function tryNpx(version) {
|
|
113
133
|
if (!commandOnPath('npx')) return false;
|
|
114
134
|
const spec = version ? `@geraldmaron/construct@${version}` : '@geraldmaron/construct';
|
|
135
|
+
|
|
136
|
+
// npx exits non-zero when the pinned version is unpublished/yanked or the registry
|
|
137
|
+
// is unreachable. runForeground hands the process to npx and exits with its status,
|
|
138
|
+
// so that failure can never fall through to the global/cache/Docker resolvers below.
|
|
139
|
+
// Confirm the spec resolves first; on a miss, defer instead of dead-ending the chain.
|
|
140
|
+
|
|
141
|
+
const probe = spawnSync('npm', ['view', spec, 'version'], { stdio: 'ignore', timeout: 8000 });
|
|
142
|
+
if (probe.status !== 0) return false;
|
|
115
143
|
runForeground('npx', ['-p', spec, '--', 'construct', ...process.argv.slice(2)]);
|
|
116
144
|
return true;
|
|
117
145
|
}
|
|
@@ -179,6 +207,7 @@ function fail() {
|
|
|
179
207
|
const version = readPinnedVersion();
|
|
180
208
|
|
|
181
209
|
if (tryDevPath()) { /* spawned */ }
|
|
210
|
+
else if (trySelfRepo()) { /* spawned */ }
|
|
182
211
|
else if (tryNodeModules()) { /* spawned */ }
|
|
183
212
|
else if (tryNpx(version)) { /* spawned */ }
|
|
184
213
|
else if (tryGlobal()) { /* spawned */ }
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Accessibility Audit: {scope-title}
|
|
2
|
+
|
|
3
|
+
- **Date**: {YYYY-MM-DD}
|
|
4
|
+
- **Auditor**: cx-accessibility (or named human)
|
|
5
|
+
- **Scope**: {pages / flows / components / PR}
|
|
6
|
+
- **Baseline**: WCAG 2.1 AA (unless otherwise specified)
|
|
7
|
+
- **Assistive technology used**: {VoiceOver / NVDA / JAWS / TalkBack / Switch Control / Voice Control / keyboard-only}
|
|
8
|
+
- **Verdict**: ACCESSIBLE | ISSUES_FOUND | BLOCKED
|
|
9
|
+
- **Status**: draft | final
|
|
10
|
+
|
|
11
|
+
<!--
|
|
12
|
+
Accessibility is measured by using the product, not reading the spec. Every finding cites a
|
|
13
|
+
WCAG criterion AND a concrete repro step (keyboard sequence, screen-reader output,
|
|
14
|
+
contrast measurement). A claim about assistive-tech behavior you didn't actually exercise
|
|
15
|
+
is `unverified` — not a finding.
|
|
16
|
+
-->
|
|
17
|
+
|
|
18
|
+
## Flows tested
|
|
19
|
+
<!-- The user flows actually walked through, end-to-end, with the assistive tech named above. A flow that wasn't walked isn't "passed"; it's "not tested." -->
|
|
20
|
+
|
|
21
|
+
## Findings
|
|
22
|
+
|
|
23
|
+
| WCAG Criterion | Severity | Element / Location | Repro Steps | Recommended Fix |
|
|
24
|
+
|---|---|---|---|---|
|
|
25
|
+
| {1.4.3 Contrast, 2.1.1 Keyboard, 4.1.2 Name/Role/Value, ...} | critical / high / medium / low | `{selector or path:line}` | {keystroke sequence + observed result} | {smallest change that restores compliance} |
|
|
26
|
+
|
|
27
|
+
## High-impact areas
|
|
28
|
+
|
|
29
|
+
- [ ] **Forms**: labels, error association, required-field signaling, autocomplete, focus management on validation
|
|
30
|
+
- [ ] **Images and media**: alt text correctness, captions, transcripts, decorative-vs-informative classification
|
|
31
|
+
- [ ] **Navigation**: keyboard order, skip links, landmarks, focus traps in modals
|
|
32
|
+
- [ ] **Motion and animation**: prefers-reduced-motion honored, no flashing >3 Hz, no purely-motion conveyors of meaning
|
|
33
|
+
- [ ] **Dynamic content**: live regions, status messages, async update announcements
|
|
34
|
+
- [ ] **Color and contrast**: text contrast meets AA, meaning not carried by color alone
|
|
35
|
+
- [ ] **Keyboard navigation**: every interactive element reachable and operable; no keyboard traps
|
|
36
|
+
- [ ] **Screen reader**: every interactive element exposes a name, role, and value; relationships announced
|
|
37
|
+
|
|
38
|
+
<!-- Tick what was actually exercised. An unticked box is "not audited," not "passed." -->
|
|
39
|
+
|
|
40
|
+
## Contrast measurements
|
|
41
|
+
<!-- Where contrast was checked, the measured ratio, the threshold, and pass / fail. Include the tool used (browser devtools, axe, manual measurement). -->
|
|
42
|
+
|
|
43
|
+
## Keyboard navigation
|
|
44
|
+
<!-- Sequence walked, traps found, focus-visible state. A keyboard audit that doesn't report focus indicators is incomplete. -->
|
|
45
|
+
|
|
46
|
+
## Screen reader behavior
|
|
47
|
+
<!-- For each non-trivial element: what was announced vs. what should have been. Quote the verbatim AT output where possible. -->
|
|
48
|
+
|
|
49
|
+
## Out of scope
|
|
50
|
+
<!-- Flows or surfaces not exercised. Future audits will need to cover them. -->
|
|
51
|
+
|
|
52
|
+
## Handoff
|
|
53
|
+
|
|
54
|
+
- design fixes → `next:cx-designer`
|
|
55
|
+
- code fixes → `next:cx-engineer`
|
|
56
|
+
- review of remediation → `next:cx-reviewer`
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Architecture Review: {system-or-component}
|
|
2
|
+
|
|
3
|
+
- **Date**: {YYYY-MM-DD}
|
|
4
|
+
- **Reviewer**: cx-architect (or named human)
|
|
5
|
+
- **Subject**: {existing design / proposed change / PR}
|
|
6
|
+
- **Related**: {ADR, RFC, PRD ids — link the design this review evaluates}
|
|
7
|
+
- **Verdict**: APPROVE | APPROVE_WITH_CONDITIONS | REJECT | NEEDS_REVISION
|
|
8
|
+
- **Status**: draft | final
|
|
9
|
+
|
|
10
|
+
<!--
|
|
11
|
+
An architecture review evaluates an existing or proposed design — distinct from an ADR (a
|
|
12
|
+
new decision record) or RFC (a proposal). Every concern cites the design property it
|
|
13
|
+
violates and the failure mode it enables. "I don't like it" is not a concern; "this couples
|
|
14
|
+
X and Y in a way that prevents Z" is.
|
|
15
|
+
-->
|
|
16
|
+
|
|
17
|
+
## Summary
|
|
18
|
+
<!-- 2–4 sentences: what was reviewed, the top-level verdict, the single most important concern. -->
|
|
19
|
+
|
|
20
|
+
## Design intent
|
|
21
|
+
<!-- Restate what the design is trying to achieve, in the reviewer's words. If the design's intent can't be stated clearly from the artifact, that itself is a finding. -->
|
|
22
|
+
|
|
23
|
+
## Trade-offs evaluated
|
|
24
|
+
|
|
25
|
+
| Trade-off | Option chosen | Rationale | Cost | Reversibility |
|
|
26
|
+
|---|---|---|---|---|
|
|
27
|
+
| {axis — e.g. consistency vs. availability} | {what the design picked} | {why} | {what's given up} | reversible / costly to reverse / one-way door |
|
|
28
|
+
|
|
29
|
+
## Interface contracts
|
|
30
|
+
|
|
31
|
+
| Interface | Inputs | Outputs | Error cases | Backwards compatibility |
|
|
32
|
+
|---|---|---|---|---|
|
|
33
|
+
| `{name}` | {types / shapes} | {types / shapes} | {failure modes + retry semantics} | {breaking / non-breaking + version policy} |
|
|
34
|
+
|
|
35
|
+
## Non-functional assessment
|
|
36
|
+
|
|
37
|
+
- **Scalability**: {expected load → actual capacity, with bottleneck}
|
|
38
|
+
- **Reliability**: {failure modes, blast radius, recovery}
|
|
39
|
+
- **Observability**: {what is traced, what is alerted, what isn't and why}
|
|
40
|
+
- **Security**: {trust boundaries, attack surface, sensitive data flow}
|
|
41
|
+
- **Operability**: {who runs this, how do they intervene, what's the runbook}
|
|
42
|
+
|
|
43
|
+
## Concerns
|
|
44
|
+
|
|
45
|
+
| Severity | Concern | Property violated | Failure mode enabled | Recommended change |
|
|
46
|
+
|---|---|---|---|---|
|
|
47
|
+
| critical / high / medium / low | {one-line statement} | {the design property — e.g. "single-writer per partition"} | {what breaks when this is violated} | {smallest change that restores the property} |
|
|
48
|
+
|
|
49
|
+
## Conditions for approval
|
|
50
|
+
<!-- If APPROVE_WITH_CONDITIONS, the conditions go here. Each condition is verifiable; the verdict flips back to NEEDS_REVISION if any condition isn't met. -->
|
|
51
|
+
|
|
52
|
+
## Rejected alternatives considered
|
|
53
|
+
<!-- Designs evaluated but not chosen, with the reason. An ADR-worthy review names the alternatives the original artifact didn't consider. -->
|
|
54
|
+
|
|
55
|
+
## Handoff
|
|
56
|
+
|
|
57
|
+
- changes to implement → `next:cx-engineer` or `next:cx-platform-engineer`
|
|
58
|
+
- ADR follow-up → `next:cx-architect` (capture the decision)
|
|
59
|
+
- security re-review → `next:cx-security`
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Code Review Report: {pr-title-or-bd-id}
|
|
2
|
+
|
|
3
|
+
- **Date**: {YYYY-MM-DD}
|
|
4
|
+
- **Reviewer**: cx-reviewer (or named human)
|
|
5
|
+
- **Scope**: {files / commits / PR / bd-id}
|
|
6
|
+
- **Verdict**: APPROVED | CHANGES_REQUESTED | BLOCKED
|
|
7
|
+
- **Status**: draft | final
|
|
8
|
+
|
|
9
|
+
<!--
|
|
10
|
+
A review is not approval theater. Every finding cites file:line from the diff and a concrete
|
|
11
|
+
failure scenario; severity is the impact, not the surface. Happy-path checks are not review.
|
|
12
|
+
-->
|
|
13
|
+
|
|
14
|
+
## Summary
|
|
15
|
+
<!-- 2–4 sentences: what was reviewed, the top-level verdict, what most matters. Plain language. If there are no findings, say so explicitly. -->
|
|
16
|
+
|
|
17
|
+
## Findings
|
|
18
|
+
|
|
19
|
+
| Severity | File:Line | Issue | Recommended Fix |
|
|
20
|
+
|---|---|---|---|
|
|
21
|
+
| critical / high / medium / low / nit | `path/to/file.ext:NNN` | {what's wrong, with the failure mode it enables} | {smallest safe change, or "discuss"} |
|
|
22
|
+
|
|
23
|
+
<!--
|
|
24
|
+
Severity contract:
|
|
25
|
+
- critical: shipping this regresses correctness, security, or data integrity. Block.
|
|
26
|
+
- high: likely to cause defects in production within weeks. Fix before merge.
|
|
27
|
+
- medium: real risk under specific conditions. Fix before merge, or open a tracked follow-up.
|
|
28
|
+
- low: code-quality / maintainability cost. Optional.
|
|
29
|
+
- nit: cosmetic; reviewer preference. Always optional.
|
|
30
|
+
-->
|
|
31
|
+
|
|
32
|
+
## Conditions the author did not test for
|
|
33
|
+
<!-- The point of review: name the inputs, states, and edge cases the diff doesn't account for. One bullet each, with file:line where the gap lives. -->
|
|
34
|
+
|
|
35
|
+
## Required changes
|
|
36
|
+
<!-- The minimum delta before this can merge. Empty if APPROVED. -->
|
|
37
|
+
|
|
38
|
+
## Verification
|
|
39
|
+
<!-- How a reviewer (or CI) would confirm the changes land safely. Reference the test name, the trace id, or the command that proves it. -->
|
|
40
|
+
|
|
41
|
+
## Handoff
|
|
42
|
+
<!-- Where this report goes next. Bare bd-label form so it works across hosts:
|
|
43
|
+
- findings to address → `next:cx-engineer`
|
|
44
|
+
- security concern → `next:cx-security`
|
|
45
|
+
- design / contract concern → `next:cx-architect`
|
|
46
|
+
-->
|
|
@@ -14,22 +14,22 @@ You added Construct as a dev dependency. That gave you:
|
|
|
14
14
|
|
|
15
15
|
You don't need to manage any of that: it all runs locally.
|
|
16
16
|
|
|
17
|
-
## Files Construct created
|
|
17
|
+
## Files Construct created or manages
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
Generated tooling (`.construct/`, `.claude/`, `.cx/`, `plan.md`) is gitignored; the user-owned files (`AGENTS.md`, `docs/`) are the ones committed as project content.
|
|
20
20
|
|
|
21
21
|
| Path | What it is | Touch? |
|
|
22
22
|
|---|---|---|
|
|
23
|
-
| `.construct/` | Launcher for hooks. Don't edit. Regenerated on `npm install`. | No |
|
|
24
|
-
| `.claude/agents/` | The
|
|
25
|
-
| `.claude/commands/` | Slash commands. Regenerated on `npm install`. | No |
|
|
26
|
-
| `.claude/settings.json` | Hooks + MCP server config. Construct keys are managed; your additions are preserved. | Carefully |
|
|
27
|
-
| `.cx/` | Per-project session state (active work,
|
|
23
|
+
| `.construct/` | Launcher for hooks. Don't edit. Regenerated on `npm install`. Gitignored. | No |
|
|
24
|
+
| `.claude/agents/` | The persona definitions. Regenerated on `npm install`. Gitignored. | No |
|
|
25
|
+
| `.claude/commands/` | Slash commands. Regenerated on `npm install`. Gitignored. | No |
|
|
26
|
+
| `.claude/settings.json` | Hooks + MCP server config. Construct keys are managed; your additions are preserved. Gitignored. | Carefully |
|
|
27
|
+
| `.cx/` | Per-project session state (active work, decisions, this guide). Construct writes here. Gitignored. | Read-mostly |
|
|
28
28
|
| `.beads/` | Issue tracker data. Use `bd <cmd>` to interact. | Via CLI |
|
|
29
|
-
| `AGENTS.md` |
|
|
29
|
+
| `AGENTS.md` | Agent guide. Construct owns only its fenced integration block; the rest is yours. | Yes: your house rules go here |
|
|
30
30
|
| `plan.md` | Active work plan. Local-only (gitignored). | Yes: your current focus |
|
|
31
31
|
| `docs/` | Documentation lanes (ADRs, PRDs, memos, …). | Yes: this is your team's docs |
|
|
32
|
-
|
|
|
32
|
+
| `.cx/construct_guide.md` | This file. Friendly orientation. Gitignored. | Yes: adapt to your team |
|
|
33
33
|
|
|
34
34
|
## Where to drop information you want Construct to use
|
|
35
35
|
|
|
@@ -80,16 +80,15 @@ construct doctor # verify everything's healthy
|
|
|
80
80
|
|
|
81
81
|
## Local services
|
|
82
82
|
|
|
83
|
-
|
|
83
|
+
Once services are set up (`construct install`) and you have Docker, three things run locally. Ports are derived per home directory to avoid collisions, so run `construct status` for the live endpoints rather than assuming fixed numbers.
|
|
84
84
|
|
|
85
85
|
**Telemetry backend** (LLM observability: see your traces, costs, and quality scores)
|
|
86
86
|
|
|
87
|
-
- URL:
|
|
87
|
+
- Dashboard URL: shown by `construct status`
|
|
88
88
|
|
|
89
89
|
**Postgres + pgvector** (the database that backs hybrid retrieval)
|
|
90
90
|
|
|
91
|
-
-
|
|
92
|
-
- Saved as `DATABASE_URL` in `~/.construct/config.env`
|
|
91
|
+
- Connection string (`DATABASE_URL`): shown by `construct status`, saved in `~/.construct/config.env`
|
|
93
92
|
|
|
94
93
|
**Vector storage** (semantic search over your project + ingested docs)
|
|
95
94
|
|
|
@@ -105,7 +104,8 @@ All ports bind to `127.0.0.1` only; nothing is reachable from other machines on
|
|
|
105
104
|
|
|
106
105
|
| Command | What it does |
|
|
107
106
|
|---|---|
|
|
108
|
-
| `construct
|
|
107
|
+
| `construct install` | Machine setup, once per machine: Docker, local services, `~/.construct` config |
|
|
108
|
+
| `construct init` | Project setup, once per repo: scaffold `.cx/`, AGENTS.md, plan.md, adapters |
|
|
109
109
|
| `construct config [mode <m>]` | Show active deployment mode (solo / team / enterprise) or set a new one |
|
|
110
110
|
| `construct doctor` | Health check across config, services, agents, hooks |
|
|
111
111
|
| `construct sync` | Regenerate platform adapters (Claude Code, OpenCode, Codex, Cursor) |
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Debug Investigation: {symptom-or-bd-id}
|
|
2
|
+
|
|
3
|
+
- **Date**: {YYYY-MM-DD}
|
|
4
|
+
- **Debugger**: cx-debugger (or named human)
|
|
5
|
+
- **Severity**: critical / high / medium / low
|
|
6
|
+
- **Status**: in-progress | root-cause-identified | fix-proposed | resolved
|
|
7
|
+
|
|
8
|
+
<!--
|
|
9
|
+
The real bug is always one layer deeper than where it presents. Every diagnostic claim cites
|
|
10
|
+
a stack trace, log line, test failure, or repro step. If the trace doesn't show the cause,
|
|
11
|
+
the cause is `unknown` — not a guess.
|
|
12
|
+
-->
|
|
13
|
+
|
|
14
|
+
## Capture
|
|
15
|
+
<!-- The exact error message, stack trace, log output, and repro steps as observed. Verbatim. Do not paraphrase or "clean up" the symptom. Include a path to the run log if one exists. -->
|
|
16
|
+
|
|
17
|
+
## Reproduce
|
|
18
|
+
<!-- The smallest deterministic recipe that triggers the symptom. Confirm the recipe reproduces on at least two runs. If you can't reproduce, the investigation isn't ready for a fix — say so. -->
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
{minimal repro: command, input, expected vs. actual output}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Isolate
|
|
25
|
+
<!-- Reduce the failing case until the smallest change toggles the bug. Cite the bisect range (`git bisect` boundary), the test that exhibits the failure, or the input dimension. -->
|
|
26
|
+
|
|
27
|
+
## Trace
|
|
28
|
+
<!-- The execution path from trigger to symptom. file:line citations for each hop. A trace without source pointers is a story, not a trace. -->
|
|
29
|
+
|
|
30
|
+
| Hop | Location | Observation |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| {1, 2, 3...} | `path/to/file.ext:NNN` | {what the code does here that's relevant} |
|
|
33
|
+
|
|
34
|
+
## Invariant violated
|
|
35
|
+
<!-- One sentence: the property the system was supposed to uphold, and the specific way this run violated it. The invariant is the contract; the bug is the violation. -->
|
|
36
|
+
|
|
37
|
+
## Root cause
|
|
38
|
+
<!-- The system / design condition that lets the trigger cause harm. A root cause is a system gap, never a person and never a single line of code unless that line is the design decision. -->
|
|
39
|
+
|
|
40
|
+
## Proposed fix
|
|
41
|
+
<!-- The smallest safe change that restores the invariant. If the smallest change is large, the root cause is wider than originally thought — restate it. -->
|
|
42
|
+
|
|
43
|
+
## Verification
|
|
44
|
+
<!-- The specific run, test, or check that proves the fix works. The repro from above must now pass. Cite the test name and the trace id. -->
|
|
45
|
+
|
|
46
|
+
## Follow-ups
|
|
47
|
+
<!-- Adjacent issues surfaced during the investigation. Each gets a bd id, not a paragraph. -->
|
|
48
|
+
|
|
49
|
+
## Handoff
|
|
50
|
+
|
|
51
|
+
- fix to implement → `next:cx-engineer`
|
|
52
|
+
- additional test coverage → `next:cx-qa`
|
|
53
|
+
- design review of the invariant → `next:cx-architect`
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# QA Report: {feature-or-bd-id}
|
|
2
|
+
|
|
3
|
+
- **Date**: {YYYY-MM-DD}
|
|
4
|
+
- **QA**: cx-qa (or named human)
|
|
5
|
+
- **Scope**: {feature / PR / bd-id / acceptance-criteria source}
|
|
6
|
+
- **Verdict**: PASS | FAIL | BLOCKED
|
|
7
|
+
- **Status**: draft | final
|
|
8
|
+
|
|
9
|
+
<!--
|
|
10
|
+
Coverage is a hypothesis about quality, not proof of it. Every PASS / FAIL verdict cites the
|
|
11
|
+
test name + run log line. Every coverage claim cites the report file. If a report isn't
|
|
12
|
+
available, the verdict is `unknown` — not an estimate.
|
|
13
|
+
-->
|
|
14
|
+
|
|
15
|
+
## Acceptance criteria
|
|
16
|
+
|
|
17
|
+
| Criterion | Verdict | Test name | Log line / artifact |
|
|
18
|
+
|---|---|---|---|
|
|
19
|
+
| {restated from the source — PRD, bd issue, design doc} | PASS / FAIL / unknown | `tests/path/to/test.mjs > "name"` | `{path or trace id}` |
|
|
20
|
+
|
|
21
|
+
## Coverage
|
|
22
|
+
|
|
23
|
+
| Layer | % | Source |
|
|
24
|
+
|---|---|---|
|
|
25
|
+
| Unit | {NN}% | `{coverage report path}` |
|
|
26
|
+
| Integration | {NN}% | `{report or "not run"}` |
|
|
27
|
+
| E2E | {NN}% | `{report or "not run"}` |
|
|
28
|
+
|
|
29
|
+
## Test pyramid assessment
|
|
30
|
+
<!-- Target ratio is unit:integration:E2E ≈ 70:20:10. Note the actual mix and the gap. Tests that exist but don't exercise the acceptance criterion are coverage without behavior — name them. -->
|
|
31
|
+
|
|
32
|
+
## Findings
|
|
33
|
+
|
|
34
|
+
| Test | Result | Log line / repro | Edge case it exercises |
|
|
35
|
+
|---|---|---|---|
|
|
36
|
+
| `{test name}` | PASS / FAIL / flaky | `{log line or repro steps}` | {what could break in production} |
|
|
37
|
+
|
|
38
|
+
## Coverage gaps
|
|
39
|
+
<!-- Acceptance criteria that lack a corresponding assertion, or assertions that don't exercise the acceptance criterion. Each gap names the missing test and what it should assert. -->
|
|
40
|
+
|
|
41
|
+
## Determinism
|
|
42
|
+
<!-- Tests that re-run with different results. Cite the run history (pass rate over N runs). A single failure is not flake; a single pass is not stable. -->
|
|
43
|
+
|
|
44
|
+
## Handoff
|
|
45
|
+
|
|
46
|
+
- test failures to fix → `next:cx-engineer`
|
|
47
|
+
- root cause investigation → `next:cx-debugger`
|
|
48
|
+
- flaky tests to stabilize → `next:cx-test-automation`
|