@longph2102/v-flow 1.5.0
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/AGENTS.md +265 -0
- package/CHANGELOG.md +318 -0
- package/LICENSE +21 -0
- package/README.md +326 -0
- package/agents/ba-agent.md +437 -0
- package/agents/ba-critic-agent.md +156 -0
- package/agents/ba-to-ptyc-agent.md +112 -0
- package/agents/bugfix-analyst-agent.md +221 -0
- package/agents/constitute-agent.md +155 -0
- package/agents/help-agent.md +168 -0
- package/agents/implement-agent.md +220 -0
- package/agents/import-ba-docs-agent.md +164 -0
- package/agents/master-check-agent.md +228 -0
- package/agents/metrics-agent.md +180 -0
- package/agents/operations-agent.md +123 -0
- package/agents/plan-agent.md +218 -0
- package/agents/prototype-agent.md +191 -0
- package/agents/retrospective-agent.md +196 -0
- package/agents/review-agent.md +210 -0
- package/agents/sprint-agent.md +191 -0
- package/agents/status-agent.md +186 -0
- package/agents/sync-agent.md +201 -0
- package/agents/test-agent.md +166 -0
- package/agents/understand-agent.md +339 -0
- package/cli/commands/check.js +96 -0
- package/cli/commands/dev-quiz.js +107 -0
- package/cli/commands/doctor.js +348 -0
- package/cli/commands/feature.js +259 -0
- package/cli/commands/hooks.js +163 -0
- package/cli/commands/init.js +189 -0
- package/cli/commands/log.js +199 -0
- package/cli/commands/plugin.js +230 -0
- package/cli/commands/score-card.js +203 -0
- package/cli/commands/status.js +269 -0
- package/cli/commands/sync.js +59 -0
- package/cli/commands/upgrade.js +150 -0
- package/cli/commands/validate.js +1259 -0
- package/cli/commands/watch.js +151 -0
- package/cli/index.js +46 -0
- package/cli/lib/ac-test-gate.js +89 -0
- package/cli/lib/activity-log.js +209 -0
- package/cli/lib/cli-error.js +183 -0
- package/cli/lib/constitution-lint.js +561 -0
- package/cli/lib/dev-quiz-grade.js +127 -0
- package/cli/lib/governance.js +78 -0
- package/cli/lib/hook-targets.js +167 -0
- package/cli/lib/i18n.js +375 -0
- package/cli/lib/knowledge-oracle.js +379 -0
- package/cli/lib/logger.js +203 -0
- package/cli/lib/module-card-lint.js +304 -0
- package/cli/lib/module-card-score.js +223 -0
- package/cli/lib/plugins.js +481 -0
- package/cli/lib/scanner.js +692 -0
- package/cli/lib/sync-core.js +232 -0
- package/cli/lib/sync-targets.js +84 -0
- package/cli/lib/templates.js +268 -0
- package/cli/lib/yaml-parser.js +203 -0
- package/commands/v.ba-critic.md +101 -0
- package/commands/v.ba-to-ptyc.md +71 -0
- package/commands/v.bugfix.md +86 -0
- package/commands/v.check.md +131 -0
- package/commands/v.constitute.md +87 -0
- package/commands/v.constitution.md +84 -0
- package/commands/v.fork.md +127 -0
- package/commands/v.help.md +73 -0
- package/commands/v.hotfix.md +200 -0
- package/commands/v.implement.md +92 -0
- package/commands/v.import-ba-docs.md +222 -0
- package/commands/v.metrics.md +74 -0
- package/commands/v.operations.md +70 -0
- package/commands/v.plan.md +78 -0
- package/commands/v.prototype.md +121 -0
- package/commands/v.quickfix.md +169 -0
- package/commands/v.retrospective.md +80 -0
- package/commands/v.review.md +78 -0
- package/commands/v.rewind.md +127 -0
- package/commands/v.specify.md +118 -0
- package/commands/v.sprint.md +75 -0
- package/commands/v.status.md +62 -0
- package/commands/v.sync.md +81 -0
- package/commands/v.test.md +67 -0
- package/commands/v.understand.md +112 -0
- package/package.json +65 -0
- package/skills/_shared/constitution-reader/SKILL.md +109 -0
- package/skills/_shared/constitution-reader/config.json +52 -0
- package/skills/_shared/constitution-reader/examples/good/b1-phase-output.md +48 -0
- package/skills/_shared/constitution-reader/gotchas.md +46 -0
- package/skills/_shared/context-reader/SKILL.md +111 -0
- package/skills/_shared/context-reader/config.json +54 -0
- package/skills/_shared/context-reader/examples/good/legacy-nodejs-output.md +35 -0
- package/skills/_shared/context-reader/gotchas.md +49 -0
- package/skills/_shared/ears-notation/SKILL.md +63 -0
- package/skills/_shared/ears-notation/config.json +55 -0
- package/skills/_shared/ears-notation/examples/good/plan-test-interpretation.md +29 -0
- package/skills/_shared/ears-notation/gotchas.md +43 -0
- package/skills/check/cross-validator/SKILL.md +206 -0
- package/skills/check/cross-validator/config.json +33 -0
- package/skills/check/cross-validator/examples/good/validation-report-pass-with-concerns.md +105 -0
- package/skills/check/cross-validator/gotchas.md +43 -0
- package/skills/implement/constitution-enforcer/SKILL.md +134 -0
- package/skills/implement/constitution-enforcer/config.json +16 -0
- package/skills/implement/constitution-enforcer/examples/bad/vague-report.md +42 -0
- package/skills/implement/constitution-enforcer/examples/good/compliance-report.md +57 -0
- package/skills/implement/constitution-enforcer/gotchas.md +26 -0
- package/skills/implement/constitution-enforcer/scripts/check-constitution.sh +88 -0
- package/skills/implement/no-go-zone-guard/SKILL.md +173 -0
- package/skills/implement/no-go-zone-guard/config.json +28 -0
- package/skills/implement/no-go-zone-guard/examples/good/adapter-workaround.md +46 -0
- package/skills/implement/no-go-zone-guard/gotchas.md +27 -0
- package/skills/implement/no-go-zone-guard/scripts/check-nogo-zones.sh +148 -0
- package/skills/implement/no-go-zone-guard/scripts/nogo-precommit.sh +96 -0
- package/skills/implement/tdd-driver/SKILL.md +159 -0
- package/skills/implement/tdd-driver/config.json +33 -0
- package/skills/implement/tdd-driver/examples/good/tdd-cycle-product-repo.md +81 -0
- package/skills/implement/tdd-driver/gotchas.md +34 -0
- package/skills/metrics/metrics-collector/SKILL.md +133 -0
- package/skills/metrics/metrics-collector/config.json +16 -0
- package/skills/metrics/metrics-collector/examples/bad/incomplete-report.md +48 -0
- package/skills/metrics/metrics-collector/examples/good/full-metrics-report.md +101 -0
- package/skills/metrics/metrics-collector/gotchas.md +26 -0
- package/skills/operations/incident-runbook/SKILL.md +167 -0
- package/skills/operations/incident-runbook/config.json +21 -0
- package/skills/operations/incident-runbook/examples/bad/vague-incident-report.md +48 -0
- package/skills/operations/incident-runbook/examples/good/p1-hotfix-response.md +119 -0
- package/skills/operations/incident-runbook/gotchas.md +26 -0
- package/skills/plan/architecture-designer/SKILL.md +228 -0
- package/skills/plan/architecture-designer/config.json +32 -0
- package/skills/plan/architecture-designer/examples/bad/vague-plan.md +62 -0
- package/skills/plan/architecture-designer/examples/good/expand-contract-migration.md +56 -0
- package/skills/plan/architecture-designer/examples/good/plan-structure.md +58 -0
- package/skills/plan/architecture-designer/gotchas.md +45 -0
- package/skills/plan/task-breakdown/SKILL.md +208 -0
- package/skills/plan/task-breakdown/config.json +26 -0
- package/skills/plan/task-breakdown/examples/bad/vague-tasks.md +77 -0
- package/skills/plan/task-breakdown/examples/good/spike-clarify-tasks.md +66 -0
- package/skills/plan/task-breakdown/examples/good/tasks-login-feature.md +111 -0
- package/skills/plan/task-breakdown/gotchas.md +39 -0
- package/skills/prototype/LOGIC.md +240 -0
- package/skills/prototype/SKILL.md +185 -0
- package/skills/prototype/UI.md +407 -0
- package/skills/prototype/config.json +104 -0
- package/skills/prototype/examples/bad/prototype-notes.md +68 -0
- package/skills/prototype/examples/good/prototype-notes-ui.md +109 -0
- package/skills/prototype/examples/good/prototype-notes.md +67 -0
- package/skills/prototype/gotchas.md +128 -0
- package/skills/prototype/scripts/check-flow-state.ps1 +112 -0
- package/skills/prototype/scripts/check-flow-state.sh +104 -0
- package/skills/prototype/scripts/check-prototype-cleanup.ps1 +124 -0
- package/skills/prototype/scripts/check-prototype-cleanup.sh +109 -0
- package/skills/prototype/scripts/check-prototype-notes.ps1 +107 -0
- package/skills/prototype/scripts/check-prototype-notes.sh +102 -0
- package/skills/review/adversarial-reviewer/SKILL.md +137 -0
- package/skills/review/adversarial-reviewer/config.json +32 -0
- package/skills/review/adversarial-reviewer/examples/good/review-report-template.md +56 -0
- package/skills/review/adversarial-reviewer/gotchas.md +46 -0
- package/skills/review/adversarial-reviewer/scripts/quick-security-scan.sh +52 -0
- package/skills/specify/ba-bpmn-doc-gen/SKILL.md +108 -0
- package/skills/specify/ba-bpmn-doc-gen/reference/reference-bpmn-generation.md +528 -0
- package/skills/specify/ba-bpmn-doc-gen/reference/reference-drawio-flowchart.md +466 -0
- package/skills/specify/ba-critic/SKILL.md +172 -0
- package/skills/specify/ba-critic/config.json +32 -0
- package/skills/specify/ba-critic/examples/good/critic-report-round1.md +51 -0
- package/skills/specify/ba-critic/gotchas.md +40 -0
- package/skills/specify/ba-critic/scripts/check-spec-quality.sh +72 -0
- package/skills/specify/ba-doc-generator/SKILL.md +102 -0
- package/skills/specify/ba-doc-generator/references/template-clevel.md +84 -0
- package/skills/specify/ba-doc-generator/references/template-compliance.md +83 -0
- package/skills/specify/ba-doc-generator/references/template-dev.md +138 -0
- package/skills/specify/ba-doc-generator/references/template-partner.md +167 -0
- package/skills/specify/ba-doc-generator/references/template-pm.md +92 -0
- package/skills/specify/ba-doc-generator/references/template-review.md +114 -0
- package/skills/specify/ba-doc-generator/references/template-tester.md +108 -0
- package/skills/specify/ba-doc-generator/references/template-user.md +98 -0
- package/skills/specify/bugfix-analyst/SKILL.md +296 -0
- package/skills/specify/bugfix-analyst/config.json +41 -0
- package/skills/specify/bugfix-analyst/examples/bad/common-mistakes.md +71 -0
- package/skills/specify/bugfix-analyst/examples/good/email-validation-bugfix.md +53 -0
- package/skills/specify/bugfix-analyst/gotchas.md +51 -0
- package/skills/specify/ears-writer/SKILL.md +129 -0
- package/skills/specify/ears-writer/config.json +20 -0
- package/skills/specify/ears-writer/examples/bad/common-mistakes.md +17 -0
- package/skills/specify/ears-writer/examples/good/login-requirements.md +41 -0
- package/skills/specify/ears-writer/gotchas.md +43 -0
- package/skills/specify/ears-writer/scripts/check-ears-compliance.sh +51 -0
- package/skills/test/test-case-generator/SKILL.md +161 -0
- package/skills/test/test-case-generator/config.json +33 -0
- package/skills/test/test-case-generator/examples/good/test-cases-login.md +104 -0
- package/skills/test/test-case-generator/gotchas.md +43 -0
- package/skills/understand/ba-docs-scanner/SKILL.md +239 -0
- package/skills/understand/ba-docs-scanner/config.json +47 -0
- package/skills/understand/ba-docs-scanner/examples/good/work-order-br-extract.md +28 -0
- package/skills/understand/ba-docs-scanner/gotchas.md +44 -0
- package/skills/understand/ba-docs-scanner/merge-rules.md +47 -0
- package/skills/understand/codebase-scanner/SKILL.md +260 -0
- package/skills/understand/codebase-scanner/config.json +56 -0
- package/skills/understand/codebase-scanner/examples/good/menu-module-output.md +44 -0
- package/skills/understand/codebase-scanner/gotchas.md +42 -0
- package/skills/understand/codebase-scanner/scripts/scan-project-structure.sh +64 -0
- package/templates/DESIGN.md +456 -0
- package/templates/agent-command-template.yaml +240 -0
- package/templates/agent-config-template.md +170 -0
- package/templates/agent-definition-template.md +145 -0
- package/templates/agent-metrics-template.md +150 -0
- package/templates/api-contract-template.md +72 -0
- package/templates/bugfix-report-template.md +195 -0
- package/templates/bugfix-spec-template.md +134 -0
- package/templates/code-review-report-template.md +119 -0
- package/templates/constitution-template.md +234 -0
- package/templates/context-template.md +94 -0
- package/templates/data-model-template.md +95 -0
- package/templates/decision-log-template.md +92 -0
- package/templates/flow-state-template.yaml +208 -0
- package/templates/github/workflows/v-flow-validate.yml +30 -0
- package/templates/knowledge/adr-template.md +70 -0
- package/templates/knowledge/api-contract-template.md +140 -0
- package/templates/knowledge/domain-glossary.md +29 -0
- package/templates/knowledge/golden-tests-readme.md +115 -0
- package/templates/knowledge/lessons-learned.md +41 -0
- package/templates/knowledge/patterns.md +103 -0
- package/templates/module-card/SKILL.md +85 -0
- package/templates/module-card/api-specs.md +96 -0
- package/templates/module-card/business-quiz.md +119 -0
- package/templates/module-card/cross-service.md +125 -0
- package/templates/module-card/db.md +85 -0
- package/templates/module-card/dev-quiz.md +62 -0
- package/templates/module-card/permissions.md +83 -0
- package/templates/module-card/state-diagram.md +64 -0
- package/templates/module-card/tech-context.md +90 -0
- package/templates/module-card/ui-flows.md +91 -0
- package/templates/module-card/use-cases.md +142 -0
- package/templates/module-template.yaml +161 -0
- package/templates/operations-report-template.md +108 -0
- package/templates/plan-template.md +308 -0
- package/templates/prototype-notes-template.md +116 -0
- package/templates/ptyc/PTYC.template.docx +0 -0
- package/templates/ptyc/ptyc.meta.example.yaml +44 -0
- package/templates/retrospective-report-template.md +136 -0
- package/templates/security-review-template.md +84 -0
- package/templates/session-template.md +167 -0
- package/templates/spec-review-log-template.md +75 -0
- package/templates/spec-template.md +229 -0
- package/templates/sprint-status-template.md +101 -0
- package/templates/tasks-template.md +275 -0
- package/templates/test-cases-template.md +124 -0
- package/templates/ux-checklist-template.md +79 -0
- package/templates/validation-report-template.md +125 -0
- package/templates/vflow-config-template.yaml +22 -0
|
@@ -0,0 +1,692 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scanner — Codebase static analysis module
|
|
3
|
+
*
|
|
4
|
+
* Extracted from templates.js (Phase 3 refactor).
|
|
5
|
+
* Handles: file walking, language detection, framework detection, package manager detection.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const fs = require('fs-extra');
|
|
10
|
+
|
|
11
|
+
// ============================================================
|
|
12
|
+
// CONSTANTS
|
|
13
|
+
// ============================================================
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Extension → language/type mapping
|
|
17
|
+
*/
|
|
18
|
+
const EXT_MAP = {
|
|
19
|
+
// JavaScript / TypeScript
|
|
20
|
+
'.js': 'JavaScript', '.mjs': 'JavaScript', '.cjs': 'JavaScript',
|
|
21
|
+
'.ts': 'TypeScript', '.tsx': 'TypeScript',
|
|
22
|
+
'.jsx': 'JavaScript (React)',
|
|
23
|
+
// Python
|
|
24
|
+
'.py': 'Python',
|
|
25
|
+
// Ruby
|
|
26
|
+
'.rb': 'Ruby',
|
|
27
|
+
// Go
|
|
28
|
+
'.go': 'Go',
|
|
29
|
+
// JVM
|
|
30
|
+
'.java': 'Java', '.kt': 'Kotlin',
|
|
31
|
+
// .NET
|
|
32
|
+
'.cs': 'C#', '.fs': 'F#',
|
|
33
|
+
// Systems
|
|
34
|
+
'.cpp': 'C++', '.c': 'C', '.rs': 'Rust', '.swift': 'Swift',
|
|
35
|
+
// PHP
|
|
36
|
+
'.php': 'PHP',
|
|
37
|
+
// Dart/Flutter
|
|
38
|
+
'.dart': 'Dart',
|
|
39
|
+
// Web frameworks
|
|
40
|
+
'.vue': 'Vue', '.svelte': 'Svelte',
|
|
41
|
+
// Config / Data
|
|
42
|
+
'.json': 'JSON', '.yaml': 'YAML', '.yml': 'YAML', '.toml': 'TOML',
|
|
43
|
+
'.sql': 'SQL', '.graphql': 'GraphQL',
|
|
44
|
+
// Shell
|
|
45
|
+
'.sh': 'Shell', '.bash': 'Shell',
|
|
46
|
+
// Web
|
|
47
|
+
'.html': 'HTML', '.css': 'CSS', '.scss': 'SCSS', '.sass': 'SASS',
|
|
48
|
+
// Docs
|
|
49
|
+
'.md': 'Markdown',
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/** Directories to skip when scanning */
|
|
53
|
+
const SKIP_DIRS = new Set([
|
|
54
|
+
'node_modules', '.git', '.next', '.nuxt', 'dist', 'build',
|
|
55
|
+
'out', 'coverage', '.cache', 'vendor', '__pycache__', '.venv',
|
|
56
|
+
'venv', 'env', 'target', 'bin', 'obj', '.v-flow',
|
|
57
|
+
// Flutter/Dart
|
|
58
|
+
'.dart_tool', '.fvm', '.pub-cache',
|
|
59
|
+
// iOS/macOS
|
|
60
|
+
'Pods', '.symlinks',
|
|
61
|
+
// Android
|
|
62
|
+
'.gradle',
|
|
63
|
+
]);
|
|
64
|
+
|
|
65
|
+
/** Framework detection patterns: { dep or file → label } */
|
|
66
|
+
const FRAMEWORK_PATTERNS = [
|
|
67
|
+
// JS/TS
|
|
68
|
+
{ dep: 'next', label: 'Next.js' },
|
|
69
|
+
{ dep: 'nuxt', label: 'Nuxt.js' },
|
|
70
|
+
{ dep: 'react', label: 'React' },
|
|
71
|
+
{ dep: 'vue', label: 'Vue.js' },
|
|
72
|
+
{ dep: 'svelte', label: 'Svelte' },
|
|
73
|
+
{ dep: 'express', label: 'Express.js' },
|
|
74
|
+
{ dep: 'fastify', label: 'Fastify' },
|
|
75
|
+
{ dep: 'nestjs/core', label: 'NestJS' },
|
|
76
|
+
{ dep: '@nestjs/core', label: 'NestJS' },
|
|
77
|
+
{ dep: 'hono', label: 'Hono' },
|
|
78
|
+
{ dep: 'koa', label: 'Koa' },
|
|
79
|
+
{ dep: 'remix', label: 'Remix' },
|
|
80
|
+
{ dep: 'astro', label: 'Astro' },
|
|
81
|
+
// Python
|
|
82
|
+
{ dep: 'django', label: 'Django' },
|
|
83
|
+
{ dep: 'flask', label: 'Flask' },
|
|
84
|
+
{ dep: 'fastapi', label: 'FastAPI' },
|
|
85
|
+
// Java/Kotlin
|
|
86
|
+
{ dep: 'spring-boot', label: 'Spring Boot' },
|
|
87
|
+
// Dart/Flutter
|
|
88
|
+
{ dep: 'flutter', label: 'Flutter' },
|
|
89
|
+
{ dep: 'riverpod', label: 'Riverpod' },
|
|
90
|
+
{ dep: 'bloc', label: 'BLoC' },
|
|
91
|
+
{ dep: 'provider', label: 'Provider' },
|
|
92
|
+
{ dep: 'get', label: 'GetX' },
|
|
93
|
+
// .NET
|
|
94
|
+
{ dep: 'Microsoft.AspNetCore', label: 'ASP.NET Core' },
|
|
95
|
+
{ dep: 'Microsoft.EntityFrameworkCore', label: 'Entity Framework' },
|
|
96
|
+
// Rust
|
|
97
|
+
{ dep: 'actix-web', label: 'Actix Web' },
|
|
98
|
+
{ dep: 'axum', label: 'Axum' },
|
|
99
|
+
{ dep: 'rocket', label: 'Rocket' },
|
|
100
|
+
{ dep: 'tokio', label: 'Tokio' },
|
|
101
|
+
// Go
|
|
102
|
+
{ dep: 'gin-gonic/gin', label: 'Gin' },
|
|
103
|
+
{ dep: 'gorilla/mux', label: 'Gorilla Mux' },
|
|
104
|
+
{ dep: 'labstack/echo', label: 'Echo' },
|
|
105
|
+
{ dep: 'gofiber/fiber', label: 'Fiber' },
|
|
106
|
+
// Testing
|
|
107
|
+
{ dep: 'jest', label: 'Jest' },
|
|
108
|
+
{ dep: 'vitest', label: 'Vitest' },
|
|
109
|
+
{ dep: 'pytest', label: 'pytest' },
|
|
110
|
+
{ dep: 'mocha', label: 'Mocha' },
|
|
111
|
+
{ dep: 'cypress', label: 'Cypress' },
|
|
112
|
+
{ dep: 'playwright', label: 'Playwright' },
|
|
113
|
+
{ dep: 'flutter_test', label: 'flutter_test' },
|
|
114
|
+
{ dep: 'mockito', label: 'Mockito' },
|
|
115
|
+
{ dep: 'xunit', label: 'xUnit' },
|
|
116
|
+
{ dep: 'nunit', label: 'NUnit' },
|
|
117
|
+
// DB / ORM
|
|
118
|
+
{ dep: 'prisma', label: 'Prisma' },
|
|
119
|
+
{ dep: 'typeorm', label: 'TypeORM' },
|
|
120
|
+
{ dep: 'sequelize', label: 'Sequelize' },
|
|
121
|
+
{ dep: 'mongoose', label: 'Mongoose' },
|
|
122
|
+
{ dep: 'sqlalchemy', label: 'SQLAlchemy' },
|
|
123
|
+
{ dep: 'drizzle-orm', label: 'Drizzle' },
|
|
124
|
+
// Infrastructure
|
|
125
|
+
{ dep: 'docker', label: 'Docker', fileOnly: true },
|
|
126
|
+
{ dep: 'terraform', label: 'Terraform', fileOnly: true },
|
|
127
|
+
];
|
|
128
|
+
|
|
129
|
+
/** Languages considered "code" (for primary language ranking) */
|
|
130
|
+
const CODE_LANGUAGES = [
|
|
131
|
+
'JavaScript', 'TypeScript', 'JavaScript (React)', 'Python', 'Ruby', 'Go',
|
|
132
|
+
'Java', 'Kotlin', 'C#', 'F#', 'PHP', 'Rust', 'Swift', 'Dart',
|
|
133
|
+
'C++', 'C', 'Vue', 'Svelte',
|
|
134
|
+
];
|
|
135
|
+
|
|
136
|
+
/** Testing framework labels (used to separate from regular frameworks) */
|
|
137
|
+
const TESTING_LABELS = [
|
|
138
|
+
'Jest', 'Vitest', 'Mocha', 'Cypress', 'Playwright', 'pytest',
|
|
139
|
+
'flutter_test', 'Mockito', 'xUnit', 'NUnit',
|
|
140
|
+
];
|
|
141
|
+
|
|
142
|
+
// ============================================================
|
|
143
|
+
// FILE WALKING
|
|
144
|
+
// ============================================================
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Walk directory recursively, collecting file stats.
|
|
148
|
+
* @returns {{ extCounts, totalFiles, testFiles, configFiles, entrypoints }}
|
|
149
|
+
*/
|
|
150
|
+
async function walkDir(dir, depth = 0, acc = null) {
|
|
151
|
+
if (!acc) {
|
|
152
|
+
acc = { extCounts: {}, totalFiles: 0, testFiles: [], configFiles: [], entrypoints: [] };
|
|
153
|
+
}
|
|
154
|
+
if (depth > 8) return acc;
|
|
155
|
+
|
|
156
|
+
let entries;
|
|
157
|
+
try {
|
|
158
|
+
entries = await fs.readdir(dir, { withFileTypes: true });
|
|
159
|
+
} catch {
|
|
160
|
+
return acc;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
for (const entry of entries) {
|
|
164
|
+
if (SKIP_DIRS.has(entry.name)) continue;
|
|
165
|
+
const fullPath = path.join(dir, entry.name);
|
|
166
|
+
|
|
167
|
+
if (entry.isDirectory()) {
|
|
168
|
+
await walkDir(fullPath, depth + 1, acc);
|
|
169
|
+
} else if (entry.isFile()) {
|
|
170
|
+
acc.totalFiles++;
|
|
171
|
+
const ext = path.extname(entry.name).toLowerCase();
|
|
172
|
+
if (EXT_MAP[ext]) {
|
|
173
|
+
acc.extCounts[EXT_MAP[ext]] = (acc.extCounts[EXT_MAP[ext]] || 0) + 1;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const name = entry.name.toLowerCase();
|
|
177
|
+
|
|
178
|
+
// Detect test files
|
|
179
|
+
if (isTestFile(name)) {
|
|
180
|
+
acc.testFiles.push(path.relative(dir, fullPath));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Detect config files
|
|
184
|
+
if (isConfigFile(name)) {
|
|
185
|
+
acc.configFiles.push(entry.name);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Detect likely entrypoints
|
|
189
|
+
if (isEntrypoint(name) && depth <= 3) {
|
|
190
|
+
acc.entrypoints.push(entry.name);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return acc;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/** Check if filename looks like a test file */
|
|
198
|
+
function isTestFile(name) {
|
|
199
|
+
return (
|
|
200
|
+
name.includes('.test.') ||
|
|
201
|
+
name.includes('.spec.') ||
|
|
202
|
+
name.startsWith('test_') ||
|
|
203
|
+
name.endsWith('_test.js') ||
|
|
204
|
+
name.endsWith('_test.ts') ||
|
|
205
|
+
name.endsWith('_test.dart') ||
|
|
206
|
+
name.endsWith('_test.go') ||
|
|
207
|
+
name.endsWith('_test.py') ||
|
|
208
|
+
name.endsWith('_test.rs')
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/** Check if filename is a project config file */
|
|
213
|
+
function isConfigFile(name) {
|
|
214
|
+
const configNames = [
|
|
215
|
+
'package.json', 'pom.xml', 'build.gradle', 'build.gradle.kts',
|
|
216
|
+
'requirements.txt', 'pyproject.toml', 'cargo.toml',
|
|
217
|
+
'go.mod', 'go.sum',
|
|
218
|
+
'pubspec.yaml',
|
|
219
|
+
'dockerfile', 'docker-compose.yml', 'docker-compose.yaml',
|
|
220
|
+
'.csproj', '.sln', '.fsproj',
|
|
221
|
+
'gemfile', 'mix.exs',
|
|
222
|
+
];
|
|
223
|
+
return configNames.includes(name) || name.endsWith('.csproj') || name.endsWith('.sln');
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/** Check if filename is a likely entrypoint */
|
|
227
|
+
function isEntrypoint(name) {
|
|
228
|
+
const entryNames = [
|
|
229
|
+
'main.js', 'main.ts', 'index.js', 'index.ts',
|
|
230
|
+
'app.js', 'app.ts', 'server.js', 'server.ts',
|
|
231
|
+
'main.py', 'app.py', 'main.go',
|
|
232
|
+
'main.java', 'main.dart', 'main.rs',
|
|
233
|
+
'program.cs',
|
|
234
|
+
];
|
|
235
|
+
return entryNames.includes(name);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// ============================================================
|
|
239
|
+
// DEPENDENCY READERS
|
|
240
|
+
// ============================================================
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Read package.json and return { name, version, deps, devDeps, scripts }
|
|
244
|
+
*/
|
|
245
|
+
async function readPackageJson(projectRoot) {
|
|
246
|
+
const pkgPath = path.join(projectRoot, 'package.json');
|
|
247
|
+
if (!fs.existsSync(pkgPath)) return null;
|
|
248
|
+
try {
|
|
249
|
+
const pkg = await fs.readJson(pkgPath);
|
|
250
|
+
return {
|
|
251
|
+
name: pkg.name || '',
|
|
252
|
+
version: pkg.version || '',
|
|
253
|
+
deps: Object.keys(pkg.dependencies || {}),
|
|
254
|
+
devDeps: Object.keys(pkg.devDependencies || {}),
|
|
255
|
+
scripts: Object.keys(pkg.scripts || {}),
|
|
256
|
+
};
|
|
257
|
+
} catch {
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Read requirements.txt (Python)
|
|
264
|
+
*/
|
|
265
|
+
async function readRequirementsTxt(projectRoot) {
|
|
266
|
+
const reqPath = path.join(projectRoot, 'requirements.txt');
|
|
267
|
+
if (!fs.existsSync(reqPath)) return [];
|
|
268
|
+
try {
|
|
269
|
+
const content = await fs.readFile(reqPath, 'utf8');
|
|
270
|
+
return content.split('\n')
|
|
271
|
+
.map(l => l.split('==')[0].split('>=')[0].split('~=')[0].trim().toLowerCase())
|
|
272
|
+
.filter(Boolean);
|
|
273
|
+
} catch {
|
|
274
|
+
return [];
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Read pubspec.yaml (Flutter/Dart) — simple regex-based parser
|
|
280
|
+
*/
|
|
281
|
+
async function readPubspecYaml(projectRoot) {
|
|
282
|
+
const pubspecPath = path.join(projectRoot, 'pubspec.yaml');
|
|
283
|
+
if (!fs.existsSync(pubspecPath)) return null;
|
|
284
|
+
try {
|
|
285
|
+
const content = await fs.readFile(pubspecPath, 'utf8');
|
|
286
|
+
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
287
|
+
const versionMatch = content.match(/^version:\s*(.+)$/m);
|
|
288
|
+
|
|
289
|
+
// Extract dependency names (lines under dependencies: / dev_dependencies:)
|
|
290
|
+
const deps = [];
|
|
291
|
+
const depSections = content.match(/(?:dependencies|dev_dependencies):\s*\n((?: {2}.+\n)*)/g) || [];
|
|
292
|
+
for (const section of depSections) {
|
|
293
|
+
const depLines = section.match(/^\s{2}(\w[\w_-]*?):/gm) || [];
|
|
294
|
+
for (const line of depLines) {
|
|
295
|
+
const depName = line.trim().replace(':', '');
|
|
296
|
+
deps.push(depName);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return {
|
|
301
|
+
name: nameMatch ? nameMatch[1].trim() : '',
|
|
302
|
+
version: versionMatch ? versionMatch[1].trim() : '',
|
|
303
|
+
deps,
|
|
304
|
+
};
|
|
305
|
+
} catch {
|
|
306
|
+
return null;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Read Cargo.toml (Rust) — simple regex-based parser
|
|
312
|
+
*/
|
|
313
|
+
async function readCargoToml(projectRoot) {
|
|
314
|
+
const cargoPath = path.join(projectRoot, 'Cargo.toml');
|
|
315
|
+
if (!fs.existsSync(cargoPath)) return null;
|
|
316
|
+
try {
|
|
317
|
+
const content = await fs.readFile(cargoPath, 'utf8');
|
|
318
|
+
const nameMatch = content.match(/^name\s*=\s*"(.+)"/m);
|
|
319
|
+
|
|
320
|
+
const deps = [];
|
|
321
|
+
const depSection = content.match(/\[dependencies\]([\s\S]*?)(?:\[|$)/);
|
|
322
|
+
if (depSection) {
|
|
323
|
+
const depLines = depSection[1].match(/^(\w[\w_-]*?)\s*=/gm) || [];
|
|
324
|
+
for (const line of depLines) {
|
|
325
|
+
deps.push(line.replace(/\s*=.*/, '').trim());
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
return {
|
|
330
|
+
name: nameMatch ? nameMatch[1] : '',
|
|
331
|
+
deps,
|
|
332
|
+
};
|
|
333
|
+
} catch {
|
|
334
|
+
return null;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Read go.mod (Go) — extract module name and dependencies
|
|
340
|
+
*/
|
|
341
|
+
async function readGoMod(projectRoot) {
|
|
342
|
+
const goModPath = path.join(projectRoot, 'go.mod');
|
|
343
|
+
if (!fs.existsSync(goModPath)) return null;
|
|
344
|
+
try {
|
|
345
|
+
const content = await fs.readFile(goModPath, 'utf8');
|
|
346
|
+
const moduleMatch = content.match(/^module\s+(.+)$/m);
|
|
347
|
+
|
|
348
|
+
const deps = [];
|
|
349
|
+
const requireBlock = content.match(/require\s*\(([\s\S]*?)\)/);
|
|
350
|
+
if (requireBlock) {
|
|
351
|
+
const depLines = requireBlock[1].match(/^\s*(\S+)/gm) || [];
|
|
352
|
+
for (const line of depLines) {
|
|
353
|
+
deps.push(line.trim());
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
return {
|
|
358
|
+
name: moduleMatch ? moduleMatch[1].trim() : '',
|
|
359
|
+
deps,
|
|
360
|
+
};
|
|
361
|
+
} catch {
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// ============================================================
|
|
367
|
+
// FRAMEWORK DETECTION
|
|
368
|
+
// ============================================================
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Detect frameworks from deps array
|
|
372
|
+
*/
|
|
373
|
+
function detectFrameworks(deps) {
|
|
374
|
+
const detected = [];
|
|
375
|
+
const allDeps = deps.join(' ').toLowerCase();
|
|
376
|
+
for (const { dep, label } of FRAMEWORK_PATTERNS) {
|
|
377
|
+
if (allDeps.includes(dep.toLowerCase())) {
|
|
378
|
+
detected.push(label);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return [...new Set(detected)];
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Detect frameworks from config files (Dockerfile, CI configs, etc.)
|
|
386
|
+
*/
|
|
387
|
+
function detectFromConfigFiles(configFiles) {
|
|
388
|
+
const detected = [];
|
|
389
|
+
const names = configFiles.map(f => f.toLowerCase());
|
|
390
|
+
|
|
391
|
+
if (names.some(n => n === 'dockerfile' || n.startsWith('docker-compose'))) {
|
|
392
|
+
detected.push('Docker');
|
|
393
|
+
}
|
|
394
|
+
if (names.some(n => n === '.github/workflows' || n.endsWith('.yml'))) {
|
|
395
|
+
// GitHub Actions detected separately
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
return detected;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// ============================================================
|
|
402
|
+
// PACKAGE MANAGER DETECTION
|
|
403
|
+
// ============================================================
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Detect package manager from lock files and config files
|
|
407
|
+
*/
|
|
408
|
+
function detectPackageManager(projectRoot) {
|
|
409
|
+
const checks = [
|
|
410
|
+
{ file: 'pnpm-lock.yaml', manager: 'pnpm' },
|
|
411
|
+
{ file: 'yarn.lock', manager: 'yarn' },
|
|
412
|
+
{ file: 'bun.lockb', manager: 'bun' },
|
|
413
|
+
{ file: 'package-lock.json', manager: 'npm' },
|
|
414
|
+
{ file: 'pubspec.lock', manager: 'pub' },
|
|
415
|
+
{ file: 'requirements.txt', manager: 'pip' },
|
|
416
|
+
{ file: 'Pipfile.lock', manager: 'pipenv' },
|
|
417
|
+
{ file: 'poetry.lock', manager: 'poetry' },
|
|
418
|
+
{ file: 'go.sum', manager: 'go modules' },
|
|
419
|
+
{ file: 'go.mod', manager: 'go modules' },
|
|
420
|
+
{ file: 'pom.xml', manager: 'Maven' },
|
|
421
|
+
{ file: 'build.gradle', manager: 'Gradle' },
|
|
422
|
+
{ file: 'build.gradle.kts', manager: 'Gradle' },
|
|
423
|
+
{ file: 'Cargo.lock', manager: 'Cargo' },
|
|
424
|
+
{ file: 'Cargo.toml', manager: 'Cargo' },
|
|
425
|
+
{ file: 'Gemfile.lock', manager: 'Bundler' },
|
|
426
|
+
{ file: 'mix.lock', manager: 'Mix' },
|
|
427
|
+
];
|
|
428
|
+
|
|
429
|
+
for (const { file, manager } of checks) {
|
|
430
|
+
if (fs.existsSync(path.join(projectRoot, file))) {
|
|
431
|
+
return manager;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
return 'unknown';
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// ============================================================
|
|
439
|
+
// MAIN SCANNER
|
|
440
|
+
// ============================================================
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Main scanner — runs all static analysis and returns a summary object
|
|
444
|
+
*/
|
|
445
|
+
async function scanCodebase(projectRoot) {
|
|
446
|
+
const today = new Date().toISOString().split('T')[0];
|
|
447
|
+
const result = {
|
|
448
|
+
scannedAt: today,
|
|
449
|
+
projectName: path.basename(projectRoot),
|
|
450
|
+
languages: [],
|
|
451
|
+
frameworks: [],
|
|
452
|
+
testingTools: [],
|
|
453
|
+
hasTests: false,
|
|
454
|
+
testFileCount: 0,
|
|
455
|
+
totalFiles: 0,
|
|
456
|
+
entrypoints: [],
|
|
457
|
+
configFiles: [],
|
|
458
|
+
packageManager: 'unknown',
|
|
459
|
+
rawExtCounts: {},
|
|
460
|
+
};
|
|
461
|
+
|
|
462
|
+
// Walk directory
|
|
463
|
+
const walk = await walkDir(projectRoot);
|
|
464
|
+
result.totalFiles = walk.totalFiles;
|
|
465
|
+
result.testFileCount = walk.testFiles.length;
|
|
466
|
+
result.hasTests = walk.testFiles.length > 0;
|
|
467
|
+
result.entrypoints = [...new Set(walk.entrypoints)].slice(0, 5);
|
|
468
|
+
result.configFiles = walk.configFiles;
|
|
469
|
+
result.rawExtCounts = walk.extCounts;
|
|
470
|
+
|
|
471
|
+
// Top languages (exclude non-code types)
|
|
472
|
+
result.languages = Object.entries(walk.extCounts)
|
|
473
|
+
.filter(([lang]) => CODE_LANGUAGES.includes(lang))
|
|
474
|
+
.sort((a, b) => b[1] - a[1])
|
|
475
|
+
.map(([lang]) => lang)
|
|
476
|
+
.slice(0, 5);
|
|
477
|
+
|
|
478
|
+
// Package manager detection
|
|
479
|
+
result.packageManager = detectPackageManager(projectRoot);
|
|
480
|
+
|
|
481
|
+
// Framework detection from package.json (Node.js)
|
|
482
|
+
const pkg = await readPackageJson(projectRoot);
|
|
483
|
+
if (pkg) {
|
|
484
|
+
const allDeps = [...pkg.deps, ...pkg.devDeps];
|
|
485
|
+
const allFrameworks = detectFrameworks(allDeps);
|
|
486
|
+
result.testingTools = allFrameworks.filter(f => TESTING_LABELS.includes(f));
|
|
487
|
+
result.frameworks = allFrameworks.filter(f => !TESTING_LABELS.includes(f));
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
// Python deps
|
|
491
|
+
const pyDeps = await readRequirementsTxt(projectRoot);
|
|
492
|
+
if (pyDeps.length > 0) {
|
|
493
|
+
const pyFrameworks = detectFrameworks(pyDeps);
|
|
494
|
+
result.frameworks.push(...pyFrameworks.filter(f => !result.frameworks.includes(f)));
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// Dart/Flutter deps
|
|
498
|
+
const pubspec = await readPubspecYaml(projectRoot);
|
|
499
|
+
if (pubspec) {
|
|
500
|
+
if (pubspec.name && !pkg) {
|
|
501
|
+
result.projectName = pubspec.name;
|
|
502
|
+
}
|
|
503
|
+
const dartFrameworks = detectFrameworks(pubspec.deps);
|
|
504
|
+
const dartTesting = dartFrameworks.filter(f => TESTING_LABELS.includes(f));
|
|
505
|
+
const dartRegular = dartFrameworks.filter(f => !TESTING_LABELS.includes(f));
|
|
506
|
+
result.frameworks.push(...dartRegular.filter(f => !result.frameworks.includes(f)));
|
|
507
|
+
result.testingTools.push(...dartTesting.filter(f => !result.testingTools.includes(f)));
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// Rust deps
|
|
511
|
+
const cargo = await readCargoToml(projectRoot);
|
|
512
|
+
if (cargo) {
|
|
513
|
+
if (cargo.name && !pkg && !pubspec) {
|
|
514
|
+
result.projectName = cargo.name;
|
|
515
|
+
}
|
|
516
|
+
const rustFrameworks = detectFrameworks(cargo.deps);
|
|
517
|
+
result.frameworks.push(...rustFrameworks.filter(f => !result.frameworks.includes(f)));
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// Go deps
|
|
521
|
+
const goMod = await readGoMod(projectRoot);
|
|
522
|
+
if (goMod) {
|
|
523
|
+
if (goMod.name && !pkg && !pubspec && !cargo) {
|
|
524
|
+
result.projectName = path.basename(goMod.name);
|
|
525
|
+
}
|
|
526
|
+
const goFrameworks = detectFrameworks(goMod.deps);
|
|
527
|
+
result.frameworks.push(...goFrameworks.filter(f => !result.frameworks.includes(f)));
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// Config-file-based detection (Docker, etc.)
|
|
531
|
+
const configFrameworks = detectFromConfigFiles(walk.configFiles);
|
|
532
|
+
result.frameworks.push(...configFrameworks.filter(f => !result.frameworks.includes(f)));
|
|
533
|
+
|
|
534
|
+
return result;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// ============================================================
|
|
538
|
+
// CONTEXT.MD GENERATOR
|
|
539
|
+
// ============================================================
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Generate context.md content from scan result
|
|
543
|
+
*/
|
|
544
|
+
function generateContextMd(scan) {
|
|
545
|
+
const langList = scan.languages.length > 0 ? scan.languages.join(', ') : '*(chưa phát hiện — tự điền)*';
|
|
546
|
+
const frameworkList = scan.frameworks.length > 0 ? scan.frameworks.join(', ') : '*(chưa phát hiện — tự điền)*';
|
|
547
|
+
const testingList = scan.testingTools.length > 0 ? scan.testingTools.join(', ') : '*(không tìm thấy)*';
|
|
548
|
+
const hasTests = scan.hasTests ? `✅ Có (${scan.testFileCount} test files phát hiện)` : '❌ Không tìm thấy test files';
|
|
549
|
+
const entrypointList = scan.entrypoints.length > 0
|
|
550
|
+
? scan.entrypoints.map(e => `| \`${e}\` | *(tự điền mô tả)* |`).join('\n')
|
|
551
|
+
: '| *(tự xác định)* | |';
|
|
552
|
+
|
|
553
|
+
return `# context.md — Codebase Understanding Report
|
|
554
|
+
|
|
555
|
+
> **Phase**: U.0 (Understand)
|
|
556
|
+
> **Dự án**: ${scan.projectName}
|
|
557
|
+
> **Ngày tạo**: ${scan.scannedAt} (auto-generated by v-flow init)
|
|
558
|
+
> **Cập nhật lần cuối**: ${scan.scannedAt}
|
|
559
|
+
> **Người review**: *(Tech Lead cần review và bổ sung)*
|
|
560
|
+
|
|
561
|
+
---
|
|
562
|
+
|
|
563
|
+
## ⚠️ Nguyên tắc của file này
|
|
564
|
+
|
|
565
|
+
> **Ghi thực trạng** — không phải "should be". Không lý tưởng hóa.
|
|
566
|
+
> File này là **input bắt buộc** cho mọi Agent trước khi làm feature trên dự án này.
|
|
567
|
+
> Các mục đánh dấu \`*(tự điền)*\` cần được Tech Lead bổ sung thủ công.
|
|
568
|
+
|
|
569
|
+
---
|
|
570
|
+
|
|
571
|
+
## 1. Tech Stack Thực Tế
|
|
572
|
+
|
|
573
|
+
*🤖 Auto-detected (${scan.scannedAt}) — ${scan.totalFiles} files scanned*
|
|
574
|
+
|
|
575
|
+
| Hạng mục | Công nghệ |
|
|
576
|
+
|----------|-----------|
|
|
577
|
+
| **Ngôn ngữ chính** | ${langList} |
|
|
578
|
+
| **Framework** | ${frameworkList} |
|
|
579
|
+
| **Package manager** | ${scan.packageManager} |
|
|
580
|
+
| **Testing** | ${testingList} |
|
|
581
|
+
| **Database** | *(tự điền)* |
|
|
582
|
+
| **Cache** | *(tự điền)* |
|
|
583
|
+
| **CI/CD** | *(tự điền)* |
|
|
584
|
+
| **Deployment** | *(tự điền)* |
|
|
585
|
+
|
|
586
|
+
---
|
|
587
|
+
|
|
588
|
+
## 2. Kiến Trúc Thực Tế
|
|
589
|
+
|
|
590
|
+
> ⚠️ Mô tả kiến trúc như nó đang tồn tại, không phải lý tưởng.
|
|
591
|
+
|
|
592
|
+
### Cấu trúc thư mục chính
|
|
593
|
+
|
|
594
|
+
\`\`\`
|
|
595
|
+
*(Tech Lead điền vào — chạy \`tree -d -L 2\` hoặc xem trong IDE)*
|
|
596
|
+
\`\`\`
|
|
597
|
+
|
|
598
|
+
### Các Layer / Module chính
|
|
599
|
+
|
|
600
|
+
| Module | Vai trò | File/Folder chính |
|
|
601
|
+
|--------|---------|------------------|
|
|
602
|
+
| *(tự điền)* | | |
|
|
603
|
+
|
|
604
|
+
---
|
|
605
|
+
|
|
606
|
+
## 3. Entry Points
|
|
607
|
+
|
|
608
|
+
*🤖 Phát hiện tự động — kiểm tra lại độ chính xác*
|
|
609
|
+
|
|
610
|
+
| Entry Point | File phát hiện |
|
|
611
|
+
|-------------|---------------|
|
|
612
|
+
${entrypointList}
|
|
613
|
+
| *(bổ sung thêm nếu cần)* | |
|
|
614
|
+
|
|
615
|
+
---
|
|
616
|
+
|
|
617
|
+
## 4. 🚫 No-Go Zones
|
|
618
|
+
|
|
619
|
+
> **Đây là luật**: Agent KHÔNG được tự ý sửa các vùng này.
|
|
620
|
+
> *(Tech Lead điền vào — là phần quan trọng nhất cần bổ sung)*
|
|
621
|
+
|
|
622
|
+
| Vùng code | Lý do không nên đụng | Rủi ro |
|
|
623
|
+
|-----------|---------------------|--------|
|
|
624
|
+
| *(tự điền)* | | Cao/Trung/Thấp |
|
|
625
|
+
|
|
626
|
+
---
|
|
627
|
+
|
|
628
|
+
## 5. Technical Debt Nổi Bật
|
|
629
|
+
|
|
630
|
+
| Mức độ | Mô tả | Kế hoạch fix |
|
|
631
|
+
|--------|-------|--------------|
|
|
632
|
+
| 🔴 Cao | *(tự điền)* | |
|
|
633
|
+
| 🟡 Trung bình | *(tự điền)* | |
|
|
634
|
+
|
|
635
|
+
---
|
|
636
|
+
|
|
637
|
+
## 6. Test Coverage Hiện Tại
|
|
638
|
+
|
|
639
|
+
*🤖 Auto-detected*
|
|
640
|
+
|
|
641
|
+
| Loại | Kết quả |
|
|
642
|
+
|------|---------|
|
|
643
|
+
| Test files phát hiện | ${scan.testFileCount} files |
|
|
644
|
+
| Có test không? | ${hasTests} |
|
|
645
|
+
| Coverage ước tính | *(chạy test để biết chính xác)* |
|
|
646
|
+
|
|
647
|
+
**Vùng không có test** (nguy hiểm nhất):
|
|
648
|
+
- [ ] *(Tech Lead điền vào)*
|
|
649
|
+
|
|
650
|
+
---
|
|
651
|
+
|
|
652
|
+
## 7. Patterns Đang Dùng (Dù Không Chính Thức)
|
|
653
|
+
|
|
654
|
+
*(Tech Lead điền vào sau khi review codebase)*
|
|
655
|
+
|
|
656
|
+
- **Naming**: *(xyz)*
|
|
657
|
+
- **Error handling**: *(xyz)*
|
|
658
|
+
- **State management**: *(xyz)*
|
|
659
|
+
|
|
660
|
+
---
|
|
661
|
+
|
|
662
|
+
## 8. Lịch Sử Cập Nhật
|
|
663
|
+
|
|
664
|
+
| Ngày | Người cập nhật | Lý do cập nhật |
|
|
665
|
+
|------|---------------|----------------|
|
|
666
|
+
| ${scan.scannedAt} | v-flow init | Tạo mới (U.0 auto-scan) |
|
|
667
|
+
`;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
module.exports = {
|
|
671
|
+
// Constants (exported for testing)
|
|
672
|
+
EXT_MAP,
|
|
673
|
+
SKIP_DIRS,
|
|
674
|
+
FRAMEWORK_PATTERNS,
|
|
675
|
+
CODE_LANGUAGES,
|
|
676
|
+
TESTING_LABELS,
|
|
677
|
+
// Functions
|
|
678
|
+
walkDir,
|
|
679
|
+
isTestFile,
|
|
680
|
+
isConfigFile,
|
|
681
|
+
isEntrypoint,
|
|
682
|
+
readPackageJson,
|
|
683
|
+
readRequirementsTxt,
|
|
684
|
+
readPubspecYaml,
|
|
685
|
+
readCargoToml,
|
|
686
|
+
readGoMod,
|
|
687
|
+
detectFrameworks,
|
|
688
|
+
detectFromConfigFiles,
|
|
689
|
+
detectPackageManager,
|
|
690
|
+
scanCodebase,
|
|
691
|
+
generateContextMd,
|
|
692
|
+
};
|