@agile-vibe-coding/avc 0.2.3 → 0.3.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/README.md +475 -3
- package/cli/agents/agent-selector.md +23 -0
- package/cli/agents/code-implementer.md +117 -0
- package/cli/agents/code-validator.md +80 -0
- package/cli/agents/context-reviewer-epic.md +101 -0
- package/cli/agents/context-reviewer-story.md +92 -0
- package/cli/agents/context-writer-epic.md +145 -0
- package/cli/agents/context-writer-story.md +111 -0
- package/cli/agents/doc-writer-epic.md +42 -0
- package/cli/agents/doc-writer-story.md +43 -0
- package/cli/agents/duplicate-detector.md +110 -0
- package/cli/agents/epic-story-decomposer.md +318 -39
- package/cli/agents/mission-scope-generator.md +68 -4
- package/cli/agents/mission-scope-validator.md +40 -6
- package/cli/agents/project-context-extractor.md +21 -6
- package/cli/agents/scaffolding-generator.md +99 -0
- package/cli/agents/seed-validator.md +71 -0
- package/cli/agents/story-scope-reviewer.md +147 -0
- package/cli/agents/story-splitter.md +83 -0
- package/cli/agents/validator-documentation.json +31 -0
- package/cli/agents/validator-documentation.md +3 -1
- package/cli/api-reference-tool.js +368 -0
- package/cli/checks/catalog.json +76 -0
- package/cli/checks/code/quality.json +26 -0
- package/cli/checks/code/testing.json +14 -0
- package/cli/checks/code/traceability.json +26 -0
- package/cli/checks/cross-refs/epic.json +171 -0
- package/cli/checks/cross-refs/story.json +149 -0
- package/cli/checks/epic/api.json +114 -0
- package/cli/checks/epic/backend.json +126 -0
- package/cli/checks/epic/cloud.json +126 -0
- package/cli/checks/epic/data.json +102 -0
- package/cli/checks/epic/database.json +114 -0
- package/cli/checks/epic/developer.json +182 -0
- package/cli/checks/epic/devops.json +174 -0
- package/cli/checks/epic/frontend.json +162 -0
- package/cli/checks/epic/mobile.json +102 -0
- package/cli/checks/epic/qa.json +90 -0
- package/cli/checks/epic/security.json +184 -0
- package/cli/checks/epic/solution-architect.json +192 -0
- package/cli/checks/epic/test-architect.json +90 -0
- package/cli/checks/epic/ui.json +102 -0
- package/cli/checks/epic/ux.json +90 -0
- package/cli/checks/fixes/epic-fix-template.md +10 -0
- package/cli/checks/fixes/story-fix-template.md +10 -0
- package/cli/checks/story/api.json +186 -0
- package/cli/checks/story/backend.json +102 -0
- package/cli/checks/story/cloud.json +102 -0
- package/cli/checks/story/data.json +210 -0
- package/cli/checks/story/database.json +102 -0
- package/cli/checks/story/developer.json +168 -0
- package/cli/checks/story/devops.json +102 -0
- package/cli/checks/story/frontend.json +174 -0
- package/cli/checks/story/mobile.json +102 -0
- package/cli/checks/story/qa.json +210 -0
- package/cli/checks/story/security.json +198 -0
- package/cli/checks/story/solution-architect.json +230 -0
- package/cli/checks/story/test-architect.json +210 -0
- package/cli/checks/story/ui.json +102 -0
- package/cli/checks/story/ux.json +102 -0
- package/cli/coding-order.js +401 -0
- package/cli/dependency-checker.js +72 -0
- package/cli/epic-story-validator.js +284 -799
- package/cli/index.js +0 -0
- package/cli/init-model-config.js +17 -10
- package/cli/init.js +514 -92
- package/cli/kanban-server-manager.js +1 -2
- package/cli/llm-claude.js +98 -31
- package/cli/llm-gemini.js +29 -5
- package/cli/llm-local.js +493 -0
- package/cli/llm-openai.js +262 -41
- package/cli/llm-provider.js +147 -8
- package/cli/llm-token-limits.js +113 -4
- package/cli/llm-verifier.js +209 -1
- package/cli/llm-xiaomi.js +143 -0
- package/cli/message-constants.js +3 -12
- package/cli/messaging-api.js +6 -12
- package/cli/micro-check-fixer.js +335 -0
- package/cli/micro-check-runner.js +449 -0
- package/cli/micro-check-scorer.js +148 -0
- package/cli/micro-check-validator.js +538 -0
- package/cli/model-pricing.js +23 -0
- package/cli/model-selector.js +3 -2
- package/cli/prompt-logger.js +57 -0
- package/cli/repl-ink.js +106 -346
- package/cli/repl-old.js +1 -2
- package/cli/seed-processor.js +194 -24
- package/cli/sprint-planning-processor.js +2638 -289
- package/cli/template-processor.js +50 -3
- package/cli/token-tracker.js +50 -23
- package/cli/tools/generate-story-validators.js +1 -1
- package/cli/validation-router.js +70 -8
- package/cli/worktree-runner.js +654 -0
- package/kanban/client/dist/assets/index-D_KC5EQT.css +1 -0
- package/kanban/client/dist/assets/index-DjY5zqW7.js +351 -0
- package/kanban/client/dist/index.html +2 -2
- package/kanban/client/src/App.jsx +43 -14
- package/kanban/client/src/components/ceremony/AskArchPopup.jsx +7 -3
- package/kanban/client/src/components/ceremony/AskModelPopup.jsx +23 -10
- package/kanban/client/src/components/ceremony/CeremonyWorkflowModal.jsx +320 -133
- package/kanban/client/src/components/ceremony/ProviderSwitcherButton.jsx +290 -0
- package/kanban/client/src/components/ceremony/SponsorCallModal.jsx +80 -13
- package/kanban/client/src/components/ceremony/SprintPlanningModal.jsx +156 -22
- package/kanban/client/src/components/ceremony/steps/ArchitectureStep.jsx +11 -11
- package/kanban/client/src/components/ceremony/steps/CompleteStep.jsx +3 -21
- package/kanban/client/src/components/ceremony/steps/ReviewAnswersStep.jsx +214 -10
- package/kanban/client/src/components/ceremony/steps/RunningStep.jsx +23 -2
- package/kanban/client/src/components/kanban/CardDetailModal.jsx +97 -10
- package/kanban/client/src/components/kanban/GroupingSelector.jsx +7 -1
- package/kanban/client/src/components/kanban/KanbanCard.jsx +23 -14
- package/kanban/client/src/components/kanban/RefineWorkItemPopup.jsx +9 -14
- package/kanban/client/src/components/kanban/RunButton.jsx +162 -0
- package/kanban/client/src/components/kanban/SeedButton.jsx +176 -0
- package/kanban/client/src/components/settings/AgentsTab.jsx +103 -75
- package/kanban/client/src/components/settings/ApiKeysTab.jsx +31 -2
- package/kanban/client/src/components/settings/CeremonyModelsTab.jsx +9 -2
- package/kanban/client/src/components/settings/CheckEditorPopup.jsx +507 -0
- package/kanban/client/src/components/settings/CostThresholdsTab.jsx +3 -2
- package/kanban/client/src/components/settings/ModelPricingTab.jsx +72 -7
- package/kanban/client/src/components/settings/OpenAIAuthSection.jsx +412 -0
- package/kanban/client/src/components/settings/SettingsModal.jsx +4 -4
- package/kanban/client/src/components/stats/CostModal.jsx +34 -3
- package/kanban/client/src/hooks/useGrouping.js +59 -0
- package/kanban/client/src/lib/api.js +118 -4
- package/kanban/client/src/lib/status-grouping.js +10 -0
- package/kanban/client/src/store/kanbanStore.js +8 -0
- package/kanban/server/index.js +23 -2
- package/kanban/server/routes/ceremony.js +153 -4
- package/kanban/server/routes/costs.js +9 -3
- package/kanban/server/routes/openai-oauth.js +366 -0
- package/kanban/server/routes/settings.js +447 -14
- package/kanban/server/routes/websocket.js +7 -2
- package/kanban/server/routes/work-items.js +141 -1
- package/kanban/server/services/CeremonyService.js +275 -24
- package/kanban/server/services/TaskRunnerService.js +261 -0
- package/kanban/server/workers/run-task-worker.js +121 -0
- package/kanban/server/workers/seed-worker.js +94 -0
- package/kanban/server/workers/sponsor-call-worker.js +14 -6
- package/kanban/server/workers/sprint-planning-worker.js +94 -12
- package/package.json +2 -3
- package/cli/agents/solver-epic-api.json +0 -15
- package/cli/agents/solver-epic-api.md +0 -39
- package/cli/agents/solver-epic-backend.json +0 -15
- package/cli/agents/solver-epic-backend.md +0 -39
- package/cli/agents/solver-epic-cloud.json +0 -15
- package/cli/agents/solver-epic-cloud.md +0 -39
- package/cli/agents/solver-epic-data.json +0 -15
- package/cli/agents/solver-epic-data.md +0 -39
- package/cli/agents/solver-epic-database.json +0 -15
- package/cli/agents/solver-epic-database.md +0 -39
- package/cli/agents/solver-epic-developer.json +0 -15
- package/cli/agents/solver-epic-developer.md +0 -39
- package/cli/agents/solver-epic-devops.json +0 -15
- package/cli/agents/solver-epic-devops.md +0 -39
- package/cli/agents/solver-epic-frontend.json +0 -15
- package/cli/agents/solver-epic-frontend.md +0 -39
- package/cli/agents/solver-epic-mobile.json +0 -15
- package/cli/agents/solver-epic-mobile.md +0 -39
- package/cli/agents/solver-epic-qa.json +0 -15
- package/cli/agents/solver-epic-qa.md +0 -39
- package/cli/agents/solver-epic-security.json +0 -15
- package/cli/agents/solver-epic-security.md +0 -39
- package/cli/agents/solver-epic-solution-architect.json +0 -15
- package/cli/agents/solver-epic-solution-architect.md +0 -39
- package/cli/agents/solver-epic-test-architect.json +0 -15
- package/cli/agents/solver-epic-test-architect.md +0 -39
- package/cli/agents/solver-epic-ui.json +0 -15
- package/cli/agents/solver-epic-ui.md +0 -39
- package/cli/agents/solver-epic-ux.json +0 -15
- package/cli/agents/solver-epic-ux.md +0 -39
- package/cli/agents/solver-story-api.json +0 -15
- package/cli/agents/solver-story-api.md +0 -39
- package/cli/agents/solver-story-backend.json +0 -15
- package/cli/agents/solver-story-backend.md +0 -39
- package/cli/agents/solver-story-cloud.json +0 -15
- package/cli/agents/solver-story-cloud.md +0 -39
- package/cli/agents/solver-story-data.json +0 -15
- package/cli/agents/solver-story-data.md +0 -39
- package/cli/agents/solver-story-database.json +0 -15
- package/cli/agents/solver-story-database.md +0 -39
- package/cli/agents/solver-story-developer.json +0 -15
- package/cli/agents/solver-story-developer.md +0 -39
- package/cli/agents/solver-story-devops.json +0 -15
- package/cli/agents/solver-story-devops.md +0 -39
- package/cli/agents/solver-story-frontend.json +0 -15
- package/cli/agents/solver-story-frontend.md +0 -39
- package/cli/agents/solver-story-mobile.json +0 -15
- package/cli/agents/solver-story-mobile.md +0 -39
- package/cli/agents/solver-story-qa.json +0 -15
- package/cli/agents/solver-story-qa.md +0 -39
- package/cli/agents/solver-story-security.json +0 -15
- package/cli/agents/solver-story-security.md +0 -39
- package/cli/agents/solver-story-solution-architect.json +0 -15
- package/cli/agents/solver-story-solution-architect.md +0 -39
- package/cli/agents/solver-story-test-architect.json +0 -15
- package/cli/agents/solver-story-test-architect.md +0 -39
- package/cli/agents/solver-story-ui.json +0 -15
- package/cli/agents/solver-story-ui.md +0 -39
- package/cli/agents/solver-story-ux.json +0 -15
- package/cli/agents/solver-story-ux.md +0 -39
- package/cli/agents/validator-epic-api.json +0 -93
- package/cli/agents/validator-epic-api.md +0 -137
- package/cli/agents/validator-epic-backend.json +0 -93
- package/cli/agents/validator-epic-backend.md +0 -130
- package/cli/agents/validator-epic-cloud.json +0 -93
- package/cli/agents/validator-epic-cloud.md +0 -137
- package/cli/agents/validator-epic-data.json +0 -93
- package/cli/agents/validator-epic-data.md +0 -130
- package/cli/agents/validator-epic-database.json +0 -93
- package/cli/agents/validator-epic-database.md +0 -137
- package/cli/agents/validator-epic-developer.json +0 -74
- package/cli/agents/validator-epic-developer.md +0 -153
- package/cli/agents/validator-epic-devops.json +0 -74
- package/cli/agents/validator-epic-devops.md +0 -153
- package/cli/agents/validator-epic-frontend.json +0 -74
- package/cli/agents/validator-epic-frontend.md +0 -153
- package/cli/agents/validator-epic-mobile.json +0 -93
- package/cli/agents/validator-epic-mobile.md +0 -130
- package/cli/agents/validator-epic-qa.json +0 -93
- package/cli/agents/validator-epic-qa.md +0 -130
- package/cli/agents/validator-epic-security.json +0 -74
- package/cli/agents/validator-epic-security.md +0 -154
- package/cli/agents/validator-epic-solution-architect.json +0 -74
- package/cli/agents/validator-epic-solution-architect.md +0 -156
- package/cli/agents/validator-epic-test-architect.json +0 -93
- package/cli/agents/validator-epic-test-architect.md +0 -130
- package/cli/agents/validator-epic-ui.json +0 -93
- package/cli/agents/validator-epic-ui.md +0 -130
- package/cli/agents/validator-epic-ux.json +0 -93
- package/cli/agents/validator-epic-ux.md +0 -130
- package/cli/agents/validator-story-api.json +0 -104
- package/cli/agents/validator-story-api.md +0 -152
- package/cli/agents/validator-story-backend.json +0 -104
- package/cli/agents/validator-story-backend.md +0 -152
- package/cli/agents/validator-story-cloud.json +0 -104
- package/cli/agents/validator-story-cloud.md +0 -152
- package/cli/agents/validator-story-data.json +0 -104
- package/cli/agents/validator-story-data.md +0 -152
- package/cli/agents/validator-story-database.json +0 -104
- package/cli/agents/validator-story-database.md +0 -152
- package/cli/agents/validator-story-developer.json +0 -104
- package/cli/agents/validator-story-developer.md +0 -152
- package/cli/agents/validator-story-devops.json +0 -104
- package/cli/agents/validator-story-devops.md +0 -152
- package/cli/agents/validator-story-frontend.json +0 -104
- package/cli/agents/validator-story-frontend.md +0 -152
- package/cli/agents/validator-story-mobile.json +0 -104
- package/cli/agents/validator-story-mobile.md +0 -152
- package/cli/agents/validator-story-qa.json +0 -104
- package/cli/agents/validator-story-qa.md +0 -152
- package/cli/agents/validator-story-security.json +0 -104
- package/cli/agents/validator-story-security.md +0 -152
- package/cli/agents/validator-story-solution-architect.json +0 -104
- package/cli/agents/validator-story-solution-architect.md +0 -152
- package/cli/agents/validator-story-test-architect.json +0 -104
- package/cli/agents/validator-story-test-architect.md +0 -152
- package/cli/agents/validator-story-ui.json +0 -104
- package/cli/agents/validator-story-ui.md +0 -152
- package/cli/agents/validator-story-ux.json +0 -104
- package/cli/agents/validator-story-ux.md +0 -152
- package/kanban/client/dist/assets/index-CiD8PS2e.js +0 -306
- package/kanban/client/dist/assets/index-nLh0m82Q.css +0 -1
|
@@ -70,6 +70,13 @@
|
|
|
70
70
|
"enabled": true,
|
|
71
71
|
"severity": "critical",
|
|
72
72
|
"description": "overallScore must be 0-100",
|
|
73
|
+
"fastPath": {
|
|
74
|
+
"enabled": true,
|
|
75
|
+
"type": "json-score-range",
|
|
76
|
+
"field": "overallScore",
|
|
77
|
+
"min": 0,
|
|
78
|
+
"max": 100
|
|
79
|
+
},
|
|
73
80
|
"check": {
|
|
74
81
|
"prompt": "Check if overallScore is valid (integer 0-100).\n\nCONTENT:\n{content}\n\nIs overallScore INVALID?\n\nRespond ONLY 'YES' or 'NO'.",
|
|
75
82
|
"expectedResponse": "YES|NO",
|
|
@@ -91,6 +98,13 @@
|
|
|
91
98
|
"enabled": true,
|
|
92
99
|
"severity": "major",
|
|
93
100
|
"description": "Severity must be critical/major/minor",
|
|
101
|
+
"fastPath": {
|
|
102
|
+
"enabled": true,
|
|
103
|
+
"type": "json-enum-deep",
|
|
104
|
+
"field": "severity",
|
|
105
|
+
"allowedValues": ["critical", "major", "minor"],
|
|
106
|
+
"searchArrays": ["structuralIssues", "contentIssues"]
|
|
107
|
+
},
|
|
94
108
|
"check": {
|
|
95
109
|
"prompt": "Check if all severity fields use ONLY: 'critical', 'major', 'minor'\n\nInvalid: 'high', 'low', 'medium'\n\nCONTENT:\n{content}\n\nAre there invalid severity values?\n\nRespond ONLY 'YES' or 'NO'.",
|
|
96
110
|
"expectedResponse": "YES|NO",
|
|
@@ -112,6 +126,12 @@
|
|
|
112
126
|
"enabled": true,
|
|
113
127
|
"severity": "critical",
|
|
114
128
|
"description": "validationStatus must be needs-improvement/acceptable/excellent",
|
|
129
|
+
"fastPath": {
|
|
130
|
+
"enabled": true,
|
|
131
|
+
"type": "json-enum",
|
|
132
|
+
"field": "validationStatus",
|
|
133
|
+
"allowedValues": ["needs-improvement", "acceptable", "excellent"]
|
|
134
|
+
},
|
|
115
135
|
"check": {
|
|
116
136
|
"prompt": "Check if validationStatus is: 'needs-improvement', 'acceptable', or 'excellent'\n\nCONTENT:\n{content}\n\nIs validationStatus INVALID?\n\nRespond ONLY 'YES' or 'NO'.",
|
|
117
137
|
"expectedResponse": "YES|NO",
|
|
@@ -133,6 +153,17 @@
|
|
|
133
153
|
"enabled": true,
|
|
134
154
|
"severity": "major",
|
|
135
155
|
"description": "Issue fields must be arrays",
|
|
156
|
+
"fastPath": {
|
|
157
|
+
"enabled": true,
|
|
158
|
+
"type": "json-arrays",
|
|
159
|
+
"arrayFields": [
|
|
160
|
+
"structuralIssues",
|
|
161
|
+
"contentIssues",
|
|
162
|
+
"applicationFlowGaps",
|
|
163
|
+
"strengths",
|
|
164
|
+
"improvementPriorities"
|
|
165
|
+
]
|
|
166
|
+
},
|
|
136
167
|
"check": {
|
|
137
168
|
"prompt": "Check if these fields are ARRAYS (not strings, not objects, not null):\n- structuralIssues\n- contentIssues\n- applicationFlowGaps\n- strengths\n- improvementPriorities\n\nExamples:\n✅ \"structuralIssues\": [] (valid - empty array)\n✅ \"contentIssues\": [{...}] (valid - array of objects)\n❌ \"strengths\": \"Good structure\" (INVALID - string not array)\n❌ \"improvementPriorities\": null (INVALID - null not array)\n\nCONTENT:\n{content}\n\nAre ALL these fields proper arrays ([], [{...}])?\n\nRespond ONLY 'YES' (all are arrays) or 'NO' (one or more not array).",
|
|
138
169
|
"expectedResponse": "YES|NO",
|
|
@@ -445,8 +445,10 @@ Otherwise, set `readyForPublication: false`.
|
|
|
445
445
|
|
|
446
446
|
## Output Requirements
|
|
447
447
|
|
|
448
|
+
⚠️ **ALL 8 FIELDS ARE MANDATORY** — your JSON MUST contain every one of these fields, even if the value is an empty array `[]`. Missing fields cause validation failures and waste processing time.
|
|
449
|
+
|
|
448
450
|
1. **Always return valid JSON** - Follow the exact structure specified
|
|
449
|
-
2. **Include
|
|
451
|
+
2. **Include ALL 8 fields** - `validationStatus`, `overallScore`, `structuralIssues`, `contentIssues`, `applicationFlowGaps`, `strengths`, `improvementPriorities`, `readyForPublication` — use empty arrays `[]` when no issues found
|
|
450
452
|
3. **Severity levels** - Only use: "critical", "major", "minor"
|
|
451
453
|
4. **Status values** - Only use: "needs-improvement", "acceptable", "excellent"
|
|
452
454
|
5. **Score range** - Must be 0-100 integer
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* api-reference-tool.js
|
|
3
|
+
*
|
|
4
|
+
* Provides an OpenAI-compatible tool definition and handler that fetches
|
|
5
|
+
* real API reference documentation from the internet. Designed to be used
|
|
6
|
+
* with local LLMs that support tool/function calling so that context writers
|
|
7
|
+
* can look up accurate payload formats, field names, and auth mechanisms
|
|
8
|
+
* instead of hallucinating them.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// Known API documentation sources
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Maps service names to documentation URLs.
|
|
17
|
+
* Each entry can have:
|
|
18
|
+
* - `openapi` — OpenAPI/Swagger spec URL (JSON or YAML)
|
|
19
|
+
* - `docs` — Human-readable docs index URL
|
|
20
|
+
* - `topics` — Map of topic keywords → specific doc URLs
|
|
21
|
+
*/
|
|
22
|
+
// No hardcoded URLs — all API references fetched dynamically via Context7.
|
|
23
|
+
// This avoids stale/broken URLs and ensures consistent, up-to-date documentation.
|
|
24
|
+
const SERVICE_REGISTRY = {};
|
|
25
|
+
|
|
26
|
+
// Aliases: normalize common service name variants
|
|
27
|
+
const SERVICE_ALIASES = {
|
|
28
|
+
// Twilio variants
|
|
29
|
+
'twilio-whatsapp': 'twilio',
|
|
30
|
+
'twilio-sms': 'twilio',
|
|
31
|
+
// Meta/WhatsApp variants (model uses many forms)
|
|
32
|
+
'meta': 'whatsapp',
|
|
33
|
+
'meta-cloud-api': 'whatsapp',
|
|
34
|
+
'meta cloud api': 'whatsapp',
|
|
35
|
+
'whatsapp-cloud': 'whatsapp',
|
|
36
|
+
'whatsapp-business': 'whatsapp',
|
|
37
|
+
'whatsapp cloud api': 'whatsapp',
|
|
38
|
+
'whatsapp business api': 'whatsapp',
|
|
39
|
+
// Express variants
|
|
40
|
+
'express.js': 'express',
|
|
41
|
+
'expressjs': 'express',
|
|
42
|
+
// AWS variants
|
|
43
|
+
's3': 'aws-s3',
|
|
44
|
+
'amazon-s3': 'aws-s3',
|
|
45
|
+
// React ecosystem
|
|
46
|
+
'react-query': 'tanstack-query',
|
|
47
|
+
'tanstack query': 'tanstack-query',
|
|
48
|
+
'@tanstack/react-query': 'tanstack-query',
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
// Dynamic discovery via Context7 (Upstash)
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
|
|
55
|
+
const CONTEXT7_BASE = 'https://context7.com/api/v2';
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Fetch topic-specific documentation from Context7.
|
|
59
|
+
* Two-step: resolve library ID → fetch docs.
|
|
60
|
+
* Works without API key; optional CONTEXT7_API_KEY env var for higher rate limits.
|
|
61
|
+
* @returns {{ libraryId: string, text: string } | null}
|
|
62
|
+
*/
|
|
63
|
+
async function fetchFromContext7(serviceName, topic) {
|
|
64
|
+
const headers = {};
|
|
65
|
+
const apiKey = process.env.CONTEXT7_API_KEY;
|
|
66
|
+
if (apiKey) headers['Authorization'] = `Bearer ${apiKey}`;
|
|
67
|
+
|
|
68
|
+
// Step 1: Resolve library ID
|
|
69
|
+
const searchUrl = `${CONTEXT7_BASE}/libs/search?query=${encodeURIComponent(serviceName)}`;
|
|
70
|
+
const searchResult = await fetchWithLimit(searchUrl, 10_000, headers);
|
|
71
|
+
if (!searchResult.ok) return null;
|
|
72
|
+
|
|
73
|
+
let libraryId;
|
|
74
|
+
try {
|
|
75
|
+
const data = JSON.parse(searchResult.body);
|
|
76
|
+
const libs = data.libraries || data;
|
|
77
|
+
if (!Array.isArray(libs) || libs.length === 0) return null;
|
|
78
|
+
// Pick highest trust match — require trust >= 5 to avoid fuzzy noise
|
|
79
|
+
// (Context7 never returns empty results; garbage queries get fuzzy matches)
|
|
80
|
+
const best = libs.sort((a, b) => (b.trust || 0) - (a.trust || 0))[0];
|
|
81
|
+
if ((best.trust || 0) < 5) return null;
|
|
82
|
+
libraryId = best.id; // format: "owner/repo" e.g. "stripe/stripe-node"
|
|
83
|
+
} catch { return null; }
|
|
84
|
+
|
|
85
|
+
// Step 2: Fetch topic-specific documentation
|
|
86
|
+
const contextUrl = `${CONTEXT7_BASE}/context?libraryId=${encodeURIComponent(libraryId)}&query=${encodeURIComponent(topic)}&type=txt&tokenLimit=5000`;
|
|
87
|
+
const contextResult = await fetchWithLimit(contextUrl, 12_000, headers);
|
|
88
|
+
if (!contextResult.ok) return null;
|
|
89
|
+
|
|
90
|
+
const text = contextResult.body?.trim();
|
|
91
|
+
if (!text || text.length < 50) return null;
|
|
92
|
+
|
|
93
|
+
return { libraryId, text };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
// Tool definition (OpenAI function-calling format)
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
|
|
100
|
+
export const API_REFERENCE_TOOL = {
|
|
101
|
+
type: 'function',
|
|
102
|
+
function: {
|
|
103
|
+
name: 'fetch_api_reference',
|
|
104
|
+
description:
|
|
105
|
+
'Fetch API reference documentation for any external service or API. ' +
|
|
106
|
+
'Supports thousands of libraries and APIs — documentation is discovered automatically. ' +
|
|
107
|
+
'Use this when you need accurate payload formats, field names, authentication mechanisms, ' +
|
|
108
|
+
'endpoint signatures, or webhook specifications.',
|
|
109
|
+
parameters: {
|
|
110
|
+
type: 'object',
|
|
111
|
+
properties: {
|
|
112
|
+
service: {
|
|
113
|
+
type: 'string',
|
|
114
|
+
description:
|
|
115
|
+
'Service or API name (e.g. "twilio", "stripe", "prisma", "shopify", "express", "supabase")',
|
|
116
|
+
},
|
|
117
|
+
topic: {
|
|
118
|
+
type: 'string',
|
|
119
|
+
description:
|
|
120
|
+
'Specific topic to look up (e.g. "webhook-payload", "authentication", "send-message", "signature-verification", "rate-limit")',
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
required: ['service', 'topic'],
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// ---------------------------------------------------------------------------
|
|
129
|
+
// Fetch helper with timeout and size limit
|
|
130
|
+
// ---------------------------------------------------------------------------
|
|
131
|
+
|
|
132
|
+
const FETCH_TIMEOUT_MS = 15_000;
|
|
133
|
+
const MAX_BODY_BYTES = 512_000; // 500 KB — enough for most doc pages
|
|
134
|
+
|
|
135
|
+
async function fetchWithLimit(url, timeoutMs = FETCH_TIMEOUT_MS, extraHeaders = {}) {
|
|
136
|
+
const controller = new AbortController();
|
|
137
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
138
|
+
try {
|
|
139
|
+
const resp = await fetch(url, {
|
|
140
|
+
signal: controller.signal,
|
|
141
|
+
headers: { 'Accept': 'text/html, application/json, text/plain, */*', ...extraHeaders },
|
|
142
|
+
});
|
|
143
|
+
if (!resp.ok) {
|
|
144
|
+
return { ok: false, error: `HTTP ${resp.status} ${resp.statusText}` };
|
|
145
|
+
}
|
|
146
|
+
const contentType = resp.headers.get('content-type') || '';
|
|
147
|
+
const buffer = await resp.arrayBuffer();
|
|
148
|
+
const body = new TextDecoder().decode(buffer.slice(0, MAX_BODY_BYTES));
|
|
149
|
+
return { ok: true, body, contentType, truncated: buffer.byteLength > MAX_BODY_BYTES };
|
|
150
|
+
} catch (err) {
|
|
151
|
+
return { ok: false, error: err.name === 'AbortError' ? 'Request timed out' : err.message };
|
|
152
|
+
} finally {
|
|
153
|
+
clearTimeout(timer);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// ---------------------------------------------------------------------------
|
|
158
|
+
// Content extractors
|
|
159
|
+
// ---------------------------------------------------------------------------
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Extract relevant text from an HTML page — strips tags, scripts, styles,
|
|
163
|
+
* and collapses whitespace. Returns a readable text summary.
|
|
164
|
+
*/
|
|
165
|
+
function extractTextFromHTML(html, maxChars = 8000) {
|
|
166
|
+
let text = html;
|
|
167
|
+
// Remove script, style, nav, footer, header blocks
|
|
168
|
+
text = text.replace(/<(script|style|nav|footer|header|aside|svg)\b[^>]*>[\s\S]*?<\/\1>/gi, ' ');
|
|
169
|
+
// Remove HTML comments
|
|
170
|
+
text = text.replace(/<!--[\s\S]*?-->/g, ' ');
|
|
171
|
+
// Convert common block elements to newlines
|
|
172
|
+
text = text.replace(/<\/(p|div|h[1-6]|li|tr|br|hr)\s*>/gi, '\n');
|
|
173
|
+
text = text.replace(/<(br|hr)\s*\/?>/gi, '\n');
|
|
174
|
+
// Strip remaining tags
|
|
175
|
+
text = text.replace(/<[^>]+>/g, ' ');
|
|
176
|
+
// Decode basic HTML entities
|
|
177
|
+
text = text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
|
178
|
+
.replace(/"/g, '"').replace(/'/g, "'").replace(/ /g, ' ');
|
|
179
|
+
// Collapse whitespace
|
|
180
|
+
text = text.replace(/[ \t]+/g, ' ').replace(/\n[ \t]+/g, '\n').replace(/\n{3,}/g, '\n\n');
|
|
181
|
+
return text.trim().slice(0, maxChars);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Extract a relevant section from an OpenAPI spec JSON for a given topic.
|
|
186
|
+
*/
|
|
187
|
+
function extractFromOpenAPI(specJson, topic) {
|
|
188
|
+
const topicLower = topic.toLowerCase();
|
|
189
|
+
const lines = [];
|
|
190
|
+
const paths = specJson.paths || {};
|
|
191
|
+
|
|
192
|
+
// Find paths matching the topic keywords
|
|
193
|
+
const keywords = topicLower.split(/[-_\s]+/);
|
|
194
|
+
const matchingPaths = Object.entries(paths).filter(([pathStr]) => {
|
|
195
|
+
const pathLower = pathStr.toLowerCase();
|
|
196
|
+
return keywords.some(kw => kw.length >= 3 && pathLower.includes(kw));
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
// Limit to first 5 matching paths
|
|
200
|
+
for (const [pathStr, methods] of matchingPaths.slice(0, 5)) {
|
|
201
|
+
lines.push(`\n### ${pathStr}`);
|
|
202
|
+
for (const [method, spec] of Object.entries(methods)) {
|
|
203
|
+
if (typeof spec !== 'object' || !spec) continue;
|
|
204
|
+
lines.push(`**${method.toUpperCase()}** — ${spec.summary || spec.description || ''}`);
|
|
205
|
+
// Request body schema
|
|
206
|
+
const reqBody = spec.requestBody?.content;
|
|
207
|
+
if (reqBody) {
|
|
208
|
+
for (const [contentType, media] of Object.entries(reqBody)) {
|
|
209
|
+
lines.push(`- Content-Type: ${contentType}`);
|
|
210
|
+
if (media.schema?.properties) {
|
|
211
|
+
const props = Object.entries(media.schema.properties).slice(0, 15);
|
|
212
|
+
for (const [prop, propSpec] of props) {
|
|
213
|
+
const req = (media.schema.required || []).includes(prop) ? ' (required)' : '';
|
|
214
|
+
lines.push(` - ${prop}: ${propSpec.type || 'any'}${req} — ${propSpec.description || ''}`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
// Response schema summary
|
|
220
|
+
const responses = spec.responses || {};
|
|
221
|
+
const successResp = responses['200'] || responses['201'] || responses['204'];
|
|
222
|
+
if (successResp) {
|
|
223
|
+
lines.push(`- Success: ${successResp.description || 'OK'}`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (lines.length === 0) {
|
|
229
|
+
// Fallback: show info section
|
|
230
|
+
const info = specJson.info || {};
|
|
231
|
+
return `API: ${info.title || 'Unknown'} (v${info.version || '?'})\n` +
|
|
232
|
+
`${info.description || ''}\n\n` +
|
|
233
|
+
`No paths matching topic "${topic}" found. Available paths (first 20):\n` +
|
|
234
|
+
Object.keys(paths).slice(0, 20).map(p => `- ${p}`).join('\n');
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const info = specJson.info || {};
|
|
238
|
+
return `API: ${info.title || 'Unknown'} (v${info.version || '?'})\n` +
|
|
239
|
+
`Topic: ${topic}\n` +
|
|
240
|
+
lines.join('\n');
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// ---------------------------------------------------------------------------
|
|
244
|
+
// Tool handler
|
|
245
|
+
// ---------------------------------------------------------------------------
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Handle a fetch_api_reference tool call.
|
|
249
|
+
* @param {{ service: string, topic: string }} args - Tool call arguments
|
|
250
|
+
* @returns {Promise<string>} The fetched API reference text
|
|
251
|
+
*/
|
|
252
|
+
export async function handleFetchApiReference({ service, topic }) {
|
|
253
|
+
const serviceLower = (service || '').toLowerCase().trim();
|
|
254
|
+
const topicLower = (topic || '').toLowerCase().trim();
|
|
255
|
+
|
|
256
|
+
// Resolve aliases
|
|
257
|
+
const resolvedService = SERVICE_ALIASES[serviceLower] || serviceLower;
|
|
258
|
+
const registry = SERVICE_REGISTRY[resolvedService];
|
|
259
|
+
|
|
260
|
+
// Tier 0: Curated registry (fastest, best quality for known services)
|
|
261
|
+
if (registry) {
|
|
262
|
+
// 1. Try topic-specific URL first
|
|
263
|
+
const topicUrl = findTopicUrl(registry.topics, topicLower);
|
|
264
|
+
if (topicUrl) {
|
|
265
|
+
console.log(`[DEBUG] API reference tool: fetching ${resolvedService}/${topicLower} from ${topicUrl}`);
|
|
266
|
+
const result = await fetchWithLimit(topicUrl);
|
|
267
|
+
if (result.ok) {
|
|
268
|
+
const text = extractTextFromHTML(result.body);
|
|
269
|
+
if (text.length > 100) {
|
|
270
|
+
return `## ${resolvedService} — ${topic}\nSource: ${topicUrl}\n\n${text}`;
|
|
271
|
+
}
|
|
272
|
+
} else {
|
|
273
|
+
console.log(`[DEBUG] API reference fetch failed: ${result.error}`);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// 2. Try OpenAPI spec for structured data
|
|
278
|
+
if (registry.openapi) {
|
|
279
|
+
console.log(`[DEBUG] API reference tool: fetching OpenAPI spec for ${resolvedService}`);
|
|
280
|
+
const specResult = await fetchWithLimit(registry.openapi, 20_000);
|
|
281
|
+
if (specResult.ok) {
|
|
282
|
+
try {
|
|
283
|
+
const spec = JSON.parse(specResult.body);
|
|
284
|
+
const extracted = extractFromOpenAPI(spec, topicLower);
|
|
285
|
+
if (extracted) {
|
|
286
|
+
return `## ${resolvedService} — ${topic} (from OpenAPI spec)\n\n${extracted}`;
|
|
287
|
+
}
|
|
288
|
+
} catch {
|
|
289
|
+
// Not valid JSON or truncated — fall through
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// 3. Fall back to general docs page
|
|
295
|
+
if (registry.docs) {
|
|
296
|
+
console.log(`[DEBUG] API reference tool: falling back to general docs for ${resolvedService}`);
|
|
297
|
+
const docsResult = await fetchWithLimit(registry.docs);
|
|
298
|
+
if (docsResult.ok) {
|
|
299
|
+
const text = extractTextFromHTML(docsResult.body, 4000);
|
|
300
|
+
return `## ${resolvedService} — general documentation\nSource: ${registry.docs}\n\n${text}\n\n` +
|
|
301
|
+
`Note: Could not find specific docs for topic "${topic}". Above is the general API docs page.`;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Tier 1: Dynamic discovery via Context7
|
|
307
|
+
console.log(`[DEBUG] API reference: "${service}" not in registry, trying Context7`);
|
|
308
|
+
const ctx7 = await fetchFromContext7(serviceLower, topicLower);
|
|
309
|
+
if (ctx7) {
|
|
310
|
+
return `## ${service} — ${topic} (via Context7: ${ctx7.libraryId})\n\n${ctx7.text}`;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
return `Could not find API documentation for "${service}/${topic}". ` +
|
|
314
|
+
`The service may not have indexed documentation available. ` +
|
|
315
|
+
`Use your training knowledge as a fallback.`;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Find the best matching topic URL from the topics map.
|
|
320
|
+
*/
|
|
321
|
+
function findTopicUrl(topics, topicLower) {
|
|
322
|
+
if (!topics) return null;
|
|
323
|
+
|
|
324
|
+
// Exact match
|
|
325
|
+
if (topics[topicLower]) return topics[topicLower];
|
|
326
|
+
|
|
327
|
+
// Partial match — find topic key that shares keywords with the query
|
|
328
|
+
const queryWords = topicLower.split(/[-_\s]+/);
|
|
329
|
+
let bestMatch = null;
|
|
330
|
+
let bestOverlap = 0;
|
|
331
|
+
|
|
332
|
+
for (const [key, url] of Object.entries(topics)) {
|
|
333
|
+
const keyWords = key.split(/[-_\s]+/);
|
|
334
|
+
const overlap = queryWords.filter(w => keyWords.includes(w)).length;
|
|
335
|
+
if (overlap > bestOverlap) {
|
|
336
|
+
bestOverlap = overlap;
|
|
337
|
+
bestMatch = url;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
return bestOverlap > 0 ? bestMatch : null;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// ---------------------------------------------------------------------------
|
|
345
|
+
// Exports for provider integration
|
|
346
|
+
// ---------------------------------------------------------------------------
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* All tools available for context generation.
|
|
350
|
+
* Providers can pass this array in the `tools` parameter of chat completions.
|
|
351
|
+
*/
|
|
352
|
+
export const CONTEXT_GENERATION_TOOLS = [API_REFERENCE_TOOL];
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Dispatch a tool call by name.
|
|
356
|
+
* @param {string} name - Tool function name
|
|
357
|
+
* @param {Object} args - Tool call arguments (parsed JSON)
|
|
358
|
+
* @returns {Promise<string>} Tool result text
|
|
359
|
+
*/
|
|
360
|
+
export async function dispatchToolCall(name, args) {
|
|
361
|
+
if (name === 'fetch_api_reference') {
|
|
362
|
+
return handleFetchApiReference(args);
|
|
363
|
+
}
|
|
364
|
+
return `Unknown tool: ${name}`;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Exported for unit testing
|
|
368
|
+
export { findTopicUrl, extractFromOpenAPI, extractTextFromHTML, fetchFromContext7 };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0.0",
|
|
3
|
+
"description": "Micro-check catalog for AVC validation system",
|
|
4
|
+
"tiers": {
|
|
5
|
+
"1": "Independent micro-checks — one YES/NO question per LLM call",
|
|
6
|
+
"2": "Cross-reference checks — validate consistency across perspectives",
|
|
7
|
+
"3": "Programmatic pattern detection — pure JS, no LLM"
|
|
8
|
+
},
|
|
9
|
+
"perspectives": [
|
|
10
|
+
"solution-architect",
|
|
11
|
+
"security",
|
|
12
|
+
"developer",
|
|
13
|
+
"devops",
|
|
14
|
+
"cloud",
|
|
15
|
+
"backend",
|
|
16
|
+
"database",
|
|
17
|
+
"api",
|
|
18
|
+
"frontend",
|
|
19
|
+
"ui",
|
|
20
|
+
"ux",
|
|
21
|
+
"mobile",
|
|
22
|
+
"data",
|
|
23
|
+
"qa",
|
|
24
|
+
"test-architect"
|
|
25
|
+
],
|
|
26
|
+
"scopes": ["epic", "story"],
|
|
27
|
+
"checkCounts": {
|
|
28
|
+
"epic": {
|
|
29
|
+
"tier1": 157,
|
|
30
|
+
"tier2": 15,
|
|
31
|
+
"byPerspective": {
|
|
32
|
+
"solution-architect": 16,
|
|
33
|
+
"security": 15,
|
|
34
|
+
"developer": 16,
|
|
35
|
+
"devops": 14,
|
|
36
|
+
"cloud": 10,
|
|
37
|
+
"backend": 10,
|
|
38
|
+
"database": 9,
|
|
39
|
+
"api": 9,
|
|
40
|
+
"frontend": 13,
|
|
41
|
+
"ui": 8,
|
|
42
|
+
"ux": 7,
|
|
43
|
+
"mobile": 8,
|
|
44
|
+
"data": 8,
|
|
45
|
+
"qa": 7,
|
|
46
|
+
"test-architect": 7
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"story": {
|
|
50
|
+
"tier1": 185,
|
|
51
|
+
"tier2": 13,
|
|
52
|
+
"byPerspective": {
|
|
53
|
+
"solution-architect": 19,
|
|
54
|
+
"security": 16,
|
|
55
|
+
"developer": 14,
|
|
56
|
+
"devops": 8,
|
|
57
|
+
"cloud": 8,
|
|
58
|
+
"backend": 8,
|
|
59
|
+
"database": 8,
|
|
60
|
+
"api": 15,
|
|
61
|
+
"frontend": 14,
|
|
62
|
+
"ui": 8,
|
|
63
|
+
"ux": 8,
|
|
64
|
+
"mobile": 8,
|
|
65
|
+
"data": 17,
|
|
66
|
+
"qa": 17,
|
|
67
|
+
"test-architect": 17
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"total": {
|
|
71
|
+
"tier1": 342,
|
|
72
|
+
"tier2": 28,
|
|
73
|
+
"all": 370
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "qual-01",
|
|
4
|
+
"severity": "major",
|
|
5
|
+
"question": "Are ALL functions 25 lines or fewer (excluding JSDoc comments and blank lines)?",
|
|
6
|
+
"evidenceGuide": "Count executable lines per function body. List any function exceeding 25 lines with its actual line count. Orchestration methods up to 50 lines are acceptable if each line is a single function call."
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"id": "qual-02",
|
|
10
|
+
"severity": "major",
|
|
11
|
+
"question": "Are business logic functions pure (no file I/O, no network calls, no database access, no console output)?",
|
|
12
|
+
"evidenceGuide": "Check non-boundary functions for side-effect calls: fs.*, fetch, database queries, console.*. Side effects must be isolated in clearly named boundary functions (e.g., readFromDatabase, writeToFile, sendApiRequest)."
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"id": "qual-03",
|
|
16
|
+
"severity": "minor",
|
|
17
|
+
"question": "Do function names use domain vocabulary from the documentation chain rather than generic programming terms?",
|
|
18
|
+
"evidenceGuide": "Compare function names against domain nouns and verbs found in the task's context.md and doc.md. Flag generic names like processData, handleRequest, doWork, updateDB. Prefer domain terms like bookAppointment, validateSlotAvailability, sendReminderMessage."
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"id": "qual-04",
|
|
22
|
+
"severity": "minor",
|
|
23
|
+
"question": "Is each source file named after its primary exported function using kebab-case with the hierarchy prefix?",
|
|
24
|
+
"evidenceGuide": "Compare file names to their primary export. Expected pattern: e0001-s0002-t0003-function-name.js for export e0001_s0002_t0003_functionName."
|
|
25
|
+
}
|
|
26
|
+
]
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "test-01",
|
|
4
|
+
"severity": "critical",
|
|
5
|
+
"question": "Do all test describe blocks reference acceptance criterion IDs in the format taskId#ACn (e.g., context-0001-0002-0003#AC1)?",
|
|
6
|
+
"evidenceGuide": "Check every describe() string in test files for an AC ID reference. The format must include the full task ID and AC number. List any describe blocks without a valid reference."
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"id": "test-02",
|
|
10
|
+
"severity": "major",
|
|
11
|
+
"question": "Is there no orphan code — does every function (exported or helper) have a @satisfies tag or belong to a module whose primary export has one?",
|
|
12
|
+
"evidenceGuide": "List any functions that cannot be traced to an acceptance criterion through either a direct @satisfies tag or membership in a file whose primary export has one."
|
|
13
|
+
}
|
|
14
|
+
]
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "trace-01",
|
|
4
|
+
"severity": "critical",
|
|
5
|
+
"question": "Do ALL exported functions and classes have the correct hierarchy prefix e{X}_s{Y}_t{Z}_ matching the task ID?",
|
|
6
|
+
"evidenceGuide": "Check every export statement. The prefix must match the task's position in the hierarchy: e{epicNum}_s{storyNum}_t{taskNum}_. List any exports missing or using wrong prefix."
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"id": "trace-02",
|
|
10
|
+
"severity": "critical",
|
|
11
|
+
"question": "Does every generated file have a provenance header with @file, @story, @task, @agent, and @generated JSDoc tags?",
|
|
12
|
+
"evidenceGuide": "Check the first JSDoc comment block at the top of each file for all five required tags. List any files missing tags."
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"id": "trace-03",
|
|
16
|
+
"severity": "critical",
|
|
17
|
+
"question": "Does every exported function have a JSDoc comment with a @satisfies tag referencing a specific acceptance criterion (e.g., context-XXXX-XXXX-XXXX#AC1)?",
|
|
18
|
+
"evidenceGuide": "Check the JSDoc block above each exported function for a @satisfies tag with a valid AC reference. List any exports without it."
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"id": "trace-04",
|
|
22
|
+
"severity": "major",
|
|
23
|
+
"question": "Is every acceptance criterion from the task's work.json covered by at least one exported function (@satisfies) AND at least one test (describe block)?",
|
|
24
|
+
"evidenceGuide": "Cross-reference the acceptance criteria array from work.json against @satisfies tags in source files and describe() strings in test files. List any uncovered ACs."
|
|
25
|
+
}
|
|
26
|
+
]
|