thachvd-kit 1.0.7 → 1.0.8
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/bin/cli.js +72 -30
- package/package.json +1 -1
- package/rules/GEMINI.md +13 -10
- package/scripts/init.py +54 -15
package/bin/cli.js
CHANGED
|
@@ -126,6 +126,20 @@ ${pc.bold('Options:')}
|
|
|
126
126
|
`);
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
+
function formatScanPreviewLines(scanned) {
|
|
130
|
+
return [
|
|
131
|
+
['Project type', scanned.project_type || 'unknown'],
|
|
132
|
+
['Primary language', scanned.primary_language || 'unknown'],
|
|
133
|
+
['Frameworks', (scanned.frameworks || []).join(', ') || 'no framework'],
|
|
134
|
+
['Database', scanned.database || 'none'],
|
|
135
|
+
['Package manager', scanned.package_manager || 'auto-detect'],
|
|
136
|
+
['Test framework', scanned.test_framework || 'auto-detect'],
|
|
137
|
+
['Cloud', scanned.cloud || 'none'],
|
|
138
|
+
['Infrastructure', (scanned.infrastructure || []).join(', ') || 'none'],
|
|
139
|
+
['CI/CD', scanned.ci_cd || 'none']
|
|
140
|
+
];
|
|
141
|
+
}
|
|
142
|
+
|
|
129
143
|
async function askQuestions(questions) {
|
|
130
144
|
return prompts(questions, {
|
|
131
145
|
onCancel: () => {
|
|
@@ -365,10 +379,11 @@ const FRAMEWORK_DETECTORS = [
|
|
|
365
379
|
id: 'django',
|
|
366
380
|
kind: 'backend',
|
|
367
381
|
language: 'python',
|
|
368
|
-
projectType: '
|
|
382
|
+
projectType: 'web-app',
|
|
369
383
|
detect: ctx => buildDetection('django', [
|
|
370
384
|
evidenceIf(textMatches(ctx.requirementsText, /\bdjango\b/i) || textMatches(ctx.pyprojectText, /\bdjango\b/i), 'Python deps -> django', 4),
|
|
371
|
-
evidenceIf(ctx.fileExists('manage.py'), 'found manage.py', 2)
|
|
385
|
+
evidenceIf(ctx.fileExists('manage.py'), 'found manage.py', 2),
|
|
386
|
+
evidenceIf(ctx.fileExists('templates'), 'found templates/', 1)
|
|
372
387
|
])
|
|
373
388
|
},
|
|
374
389
|
{
|
|
@@ -384,17 +399,18 @@ const FRAMEWORK_DETECTORS = [
|
|
|
384
399
|
id: 'laravel',
|
|
385
400
|
kind: 'backend',
|
|
386
401
|
language: 'php',
|
|
387
|
-
projectType: '
|
|
402
|
+
projectType: 'web-app',
|
|
388
403
|
detect: ctx => buildDetection('laravel', [
|
|
389
404
|
evidenceIf(hasComposerDependency(ctx.composerDepNames, 'laravel/framework'), 'composer.json -> laravel/framework', 4),
|
|
390
|
-
evidenceIf(ctx.fileExists('artisan'), 'found artisan', 3)
|
|
405
|
+
evidenceIf(ctx.fileExists('artisan'), 'found artisan', 3),
|
|
406
|
+
evidenceIf(ctx.fileExists('resources', 'views'), 'found resources/views', 1)
|
|
391
407
|
])
|
|
392
408
|
},
|
|
393
409
|
{
|
|
394
410
|
id: 'cakephp',
|
|
395
411
|
kind: 'backend',
|
|
396
412
|
language: 'php',
|
|
397
|
-
projectType: '
|
|
413
|
+
projectType: 'web-app',
|
|
398
414
|
detect: ctx => buildDetection('cakephp', [
|
|
399
415
|
evidenceIf(hasComposerDependency(ctx.composerDepNames, 'cakephp/cakephp'), 'composer.json -> cakephp/cakephp', 4),
|
|
400
416
|
evidenceIf(ctx.fileExists('bin', 'cake'), 'found bin/cake', 3),
|
|
@@ -403,18 +419,21 @@ const FRAMEWORK_DETECTORS = [
|
|
|
403
419
|
evidenceIf(ctx.fileExists('app', 'Controller', 'AppController.php'), 'found app/Controller/AppController.php', 2),
|
|
404
420
|
evidenceIf(ctx.fileExists('app', 'Model', 'AppModel.php'), 'found app/Model/AppModel.php', 2),
|
|
405
421
|
evidenceIf(ctx.fileExists('lib', 'Cake'), 'found lib/Cake', 3),
|
|
406
|
-
evidenceIf(ctx.fileExists('cake', 'console', 'cake'), 'found cake/console/cake', 3)
|
|
422
|
+
evidenceIf(ctx.fileExists('cake', 'console', 'cake'), 'found cake/console/cake', 3),
|
|
423
|
+
evidenceIf(ctx.fileExists('app', 'View'), 'found app/View', 2),
|
|
424
|
+
evidenceIf(textMatches(ctx.viewFilesText, /\.ctp$/im), 'found .ctp view templates', 2)
|
|
407
425
|
])
|
|
408
426
|
},
|
|
409
427
|
{
|
|
410
428
|
id: 'symfony',
|
|
411
429
|
kind: 'backend',
|
|
412
430
|
language: 'php',
|
|
413
|
-
projectType: '
|
|
431
|
+
projectType: 'web-app',
|
|
414
432
|
detect: ctx => buildDetection('symfony', [
|
|
415
433
|
evidenceIf(hasComposerDependency(ctx.composerDepNames, 'symfony/framework-bundle'), 'composer.json -> symfony/framework-bundle', 4),
|
|
416
434
|
evidenceIf(ctx.fileExists('bin', 'console'), 'found bin/console', 2),
|
|
417
|
-
evidenceIf(ctx.fileExists('config', 'bundles.php'), 'found config/bundles.php', 1)
|
|
435
|
+
evidenceIf(ctx.fileExists('config', 'bundles.php'), 'found config/bundles.php', 1),
|
|
436
|
+
evidenceIf(ctx.fileExists('templates'), 'found templates/', 1)
|
|
418
437
|
])
|
|
419
438
|
},
|
|
420
439
|
{
|
|
@@ -459,10 +478,11 @@ const FRAMEWORK_DETECTORS = [
|
|
|
459
478
|
id: 'rails',
|
|
460
479
|
kind: 'backend',
|
|
461
480
|
language: 'ruby',
|
|
462
|
-
projectType: '
|
|
481
|
+
projectType: 'web-app',
|
|
463
482
|
detect: ctx => buildDetection('rails', [
|
|
464
483
|
evidenceIf(textMatches(ctx.gemfileText, /^\s*gem\s+["']rails["']/im), 'Gemfile -> rails', 4),
|
|
465
|
-
evidenceIf(ctx.fileExists('bin', 'rails'), 'found bin/rails', 2)
|
|
484
|
+
evidenceIf(ctx.fileExists('bin', 'rails'), 'found bin/rails', 2),
|
|
485
|
+
evidenceIf(ctx.fileExists('app', 'views'), 'found app/views', 1)
|
|
466
486
|
])
|
|
467
487
|
},
|
|
468
488
|
{
|
|
@@ -563,7 +583,10 @@ function scanProject() {
|
|
|
563
583
|
gradleText: `${readTextIfExists('build.gradle')}\n${readTextIfExists('build.gradle.kts')}`,
|
|
564
584
|
cargoText: `${readTextIfExists('Cargo.toml')}\n${readTextIfExists('src-tauri', 'Cargo.toml')}`,
|
|
565
585
|
csprojText: rootCsproj ? readTextIfExists(rootCsproj) : '',
|
|
566
|
-
programCsText: readTextIfExists('Program.cs')
|
|
586
|
+
programCsText: readTextIfExists('Program.cs'),
|
|
587
|
+
viewFilesText: fs.existsSync(path.join(targetDir, 'app', 'View'))
|
|
588
|
+
? fs.readdirSync(path.join(targetDir, 'app', 'View'), { recursive: true }).join('\n')
|
|
589
|
+
: ''
|
|
567
590
|
};
|
|
568
591
|
|
|
569
592
|
const languageDetections = LANGUAGE_DETECTORS
|
|
@@ -605,6 +628,7 @@ function scanProject() {
|
|
|
605
628
|
if (frameworkDetails.some(item => item.projectType === 'desktop')) projectType = 'desktop';
|
|
606
629
|
else if (frameworkDetails.some(item => item.projectType === 'mobile')) projectType = 'mobile';
|
|
607
630
|
else if (frameworkDetails.some(item => item.kind === 'frontend') && frameworkDetails.some(item => item.kind === 'backend')) projectType = 'fullstack';
|
|
631
|
+
else if (frameworkDetails.some(item => item.projectType === 'web-app')) projectType = 'web-app';
|
|
608
632
|
else if (frameworkDetails.some(item => item.kind === 'backend')) projectType = 'api';
|
|
609
633
|
else if (frameworkDetails.some(item => item.kind === 'frontend')) projectType = 'web-app';
|
|
610
634
|
else if (fileExists('package.json') && pkg.bin) projectType = 'cli';
|
|
@@ -745,13 +769,24 @@ ${(data.scan_evidence || []).map(line => '- ' + line).join('\n')}
|
|
|
745
769
|
# Generated by thachvd-kit init wizard on ${new Date().toISOString().split('T')[0]}
|
|
746
770
|
# Edit freely — this is your project's brain.
|
|
747
771
|
|
|
748
|
-
## Project
|
|
749
|
-
|
|
750
|
-
- **Name:** ${data.project_name}
|
|
751
|
-
- **Description:** ${data.description}
|
|
752
|
-
- **Type:** ${data.project_type}
|
|
753
|
-
|
|
754
|
-
---
|
|
772
|
+
## Project
|
|
773
|
+
|
|
774
|
+
- **Name:** ${data.project_name}
|
|
775
|
+
- **Description:** ${data.description}
|
|
776
|
+
- **Type:** ${data.project_type}
|
|
777
|
+
|
|
778
|
+
---
|
|
779
|
+
|
|
780
|
+
## Context Status
|
|
781
|
+
|
|
782
|
+
\`\`\`yaml
|
|
783
|
+
context:
|
|
784
|
+
status: ${data.context_status || 'baseline'}
|
|
785
|
+
needs_ai_refinement: ${data.needs_ai_refinement ? 'true' : 'false'}
|
|
786
|
+
last_refined_at: ${data.last_refined_at || 'not-yet-refined'}
|
|
787
|
+
\`\`\`
|
|
788
|
+
|
|
789
|
+
---
|
|
755
790
|
|
|
756
791
|
## Stack
|
|
757
792
|
|
|
@@ -992,8 +1027,11 @@ async function main() {
|
|
|
992
1027
|
let requestAiRefinement = false;
|
|
993
1028
|
|
|
994
1029
|
if (useScan) {
|
|
995
|
-
console.log(
|
|
996
|
-
|
|
1030
|
+
console.log(` ${pc.bold('Detected context:')}`);
|
|
1031
|
+
formatScanPreviewLines(scanned).forEach(([label, value]) => {
|
|
1032
|
+
console.log(` · ${label}: ${value}`);
|
|
1033
|
+
});
|
|
1034
|
+
console.log('');
|
|
997
1035
|
if ((scanned.scan_evidence || []).length > 0) {
|
|
998
1036
|
console.log(` ${pc.bold('Evidence:')}`);
|
|
999
1037
|
scanned.scan_evidence.forEach(line => console.log(` · ${line}`));
|
|
@@ -1083,6 +1121,20 @@ async function main() {
|
|
|
1083
1121
|
data.max_file_lines = data.max_file_lines || scanned?.max_file_lines || '300';
|
|
1084
1122
|
data.framework_details = scanned?.framework_details || [];
|
|
1085
1123
|
data.scan_evidence = scanned?.scan_evidence || [];
|
|
1124
|
+
|
|
1125
|
+
if (!assumeYes) {
|
|
1126
|
+
const aiRefineAnswer = await askQuestions({
|
|
1127
|
+
type: 'confirm',
|
|
1128
|
+
name: 'ai_refine',
|
|
1129
|
+
message: 'Should the agent refine PROJECT_CONTEXT.md on first session start?',
|
|
1130
|
+
initial: useScan
|
|
1131
|
+
});
|
|
1132
|
+
requestAiRefinement = Boolean(aiRefineAnswer.ai_refine);
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
data.context_status = 'baseline';
|
|
1136
|
+
data.needs_ai_refinement = requestAiRefinement;
|
|
1137
|
+
data.last_refined_at = 'not-yet-refined';
|
|
1086
1138
|
data.infrastructure = [];
|
|
1087
1139
|
if (data.uses_docker) data.infrastructure.push('docker');
|
|
1088
1140
|
if (data.cloud !== 'none') data.infrastructure.push(data.cloud);
|
|
@@ -1118,16 +1170,6 @@ async function main() {
|
|
|
1118
1170
|
fs.writeFileSync(claudeMdPath, generateClaudeMd(data), 'utf8');
|
|
1119
1171
|
console.log(` ${pc.green('✓')} Generated ${pc.bold('CLAUDE.md')}`);
|
|
1120
1172
|
|
|
1121
|
-
if (!assumeYes) {
|
|
1122
|
-
const aiRefineAnswer = await askQuestions({
|
|
1123
|
-
type: 'confirm',
|
|
1124
|
-
name: 'ai_refine',
|
|
1125
|
-
message: 'Do you want an AI refinement prompt for PROJECT_CONTEXT.md?',
|
|
1126
|
-
initial: useScan
|
|
1127
|
-
});
|
|
1128
|
-
requestAiRefinement = Boolean(aiRefineAnswer.ai_refine);
|
|
1129
|
-
}
|
|
1130
|
-
|
|
1131
1173
|
let aiRefinementPath = null;
|
|
1132
1174
|
if (requestAiRefinement) {
|
|
1133
1175
|
aiRefinementPath = path.join(targetDir, 'AI_CONTEXT_REFINEMENT.md');
|
package/package.json
CHANGED
package/rules/GEMINI.md
CHANGED
|
@@ -10,16 +10,19 @@ trigger: always_on
|
|
|
10
10
|
|
|
11
11
|
## MANDATORY FIRST ACTION
|
|
12
12
|
|
|
13
|
-
**At session start — before anything else:**
|
|
14
|
-
|
|
15
|
-
```
|
|
16
|
-
1. Read PROJECT_CONTEXT.md (if exists) → load stack, agents, constraints
|
|
17
|
-
2. If missing → run @[skills/project-onboarding] to create it
|
|
18
|
-
3.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
13
|
+
**At session start — before anything else:**
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
1. Read PROJECT_CONTEXT.md (if exists) → load stack, agents, constraints
|
|
17
|
+
2. If missing → run @[skills/project-onboarding] to create it
|
|
18
|
+
3. Read PROJECT_CONTEXT context.status and context.needs_ai_refinement
|
|
19
|
+
4. If needs_ai_refinement = true → scan project with AI, update PROJECT_CONTEXT.md, set status=refined and needs_ai_refinement=false
|
|
20
|
+
5. Confirm: "Context loaded: [Project Name] | Stack: [Stack] | Ready."
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
> All routing decisions below depend on PROJECT_CONTEXT.md.
|
|
24
|
+
> Without it, ask user to run: `python scripts/init.py`
|
|
25
|
+
> Baseline context must be refined once when `context.needs_ai_refinement = true`.
|
|
23
26
|
|
|
24
27
|
---
|
|
25
28
|
|
package/scripts/init.py
CHANGED
|
@@ -316,14 +316,16 @@ def scan_project():
|
|
|
316
316
|
{**build_detection("django", [
|
|
317
317
|
evidence_if(text_matches(requirements, r"\bdjango\b") or text_matches(pyproject, r"\bdjango\b"), "Python deps -> django", 4),
|
|
318
318
|
evidence_if(Path("manage.py").exists(), "found manage.py", 2),
|
|
319
|
-
|
|
319
|
+
evidence_if(Path("templates").exists(), "found templates/", 1),
|
|
320
|
+
]), "kind": "backend", "project_type": "web-app", "language": "python"},
|
|
320
321
|
{**build_detection("flask", [
|
|
321
322
|
evidence_if(text_matches(requirements, r"\bflask\b") or text_matches(pyproject, r"\bflask\b"), "Python deps -> flask", 4),
|
|
322
323
|
]), "kind": "backend", "project_type": "api", "language": "python"},
|
|
323
324
|
{**build_detection("laravel", [
|
|
324
325
|
evidence_if(has_composer_dependency(composer_dep_names, "laravel/framework"), "composer.json -> laravel/framework", 4),
|
|
325
326
|
evidence_if(Path("artisan").exists(), "found artisan", 3),
|
|
326
|
-
|
|
327
|
+
evidence_if(Path("resources/views").exists(), "found resources/views", 1),
|
|
328
|
+
]), "kind": "backend", "project_type": "web-app", "language": "php"},
|
|
327
329
|
{**build_detection("cakephp", [
|
|
328
330
|
evidence_if(has_composer_dependency(composer_dep_names, "cakephp/cakephp"), "composer.json -> cakephp/cakephp", 4),
|
|
329
331
|
evidence_if(Path("bin/cake").exists(), "found bin/cake", 3),
|
|
@@ -333,12 +335,15 @@ def scan_project():
|
|
|
333
335
|
evidence_if(Path("app/Model/AppModel.php").exists(), "found app/Model/AppModel.php", 2),
|
|
334
336
|
evidence_if(Path("lib/Cake").exists(), "found lib/Cake", 3),
|
|
335
337
|
evidence_if(Path("cake/console/cake").exists(), "found cake/console/cake", 3),
|
|
336
|
-
|
|
338
|
+
evidence_if(Path("app/View").exists(), "found app/View", 2),
|
|
339
|
+
evidence_if(any(p.suffix.lower() == ".ctp" for p in Path("app/View").rglob("*.ctp")) if Path("app/View").exists() else False, "found .ctp view templates", 2),
|
|
340
|
+
]), "kind": "backend", "project_type": "web-app", "language": "php"},
|
|
337
341
|
{**build_detection("symfony", [
|
|
338
342
|
evidence_if(has_composer_dependency(composer_dep_names, "symfony/framework-bundle"), "composer.json -> symfony/framework-bundle", 4),
|
|
339
343
|
evidence_if(Path("bin/console").exists(), "found bin/console", 2),
|
|
340
344
|
evidence_if(Path("config/bundles.php").exists(), "found config/bundles.php", 1),
|
|
341
|
-
|
|
345
|
+
evidence_if(Path("templates").exists(), "found templates/", 1),
|
|
346
|
+
]), "kind": "backend", "project_type": "web-app", "language": "php"},
|
|
342
347
|
{**build_detection("codeigniter", [
|
|
343
348
|
evidence_if(has_composer_dependency(composer_dep_names, "codeigniter4/framework"), "composer.json -> codeigniter4/framework", 4),
|
|
344
349
|
evidence_if(Path("spark").exists(), "found spark", 2),
|
|
@@ -356,7 +361,8 @@ def scan_project():
|
|
|
356
361
|
{**build_detection("rails", [
|
|
357
362
|
evidence_if(text_matches(gemfile, r'^\s*gem\s+["\']rails["\']'), "Gemfile -> rails", 4),
|
|
358
363
|
evidence_if(Path("bin/rails").exists(), "found bin/rails", 2),
|
|
359
|
-
|
|
364
|
+
evidence_if(Path("app/views").exists(), "found app/views", 1),
|
|
365
|
+
]), "kind": "backend", "project_type": "web-app", "language": "ruby"},
|
|
360
366
|
{**build_detection("spring", [
|
|
361
367
|
evidence_if(text_matches(pom, r"spring-boot") or text_matches(gradle, r"spring-boot"), "Java build -> spring-boot", 4),
|
|
362
368
|
]), "kind": "backend", "project_type": "api", "language": "java"},
|
|
@@ -404,6 +410,7 @@ def scan_project():
|
|
|
404
410
|
if any(item["project_type"] == "desktop" for item in framework_details): project_type = "desktop"
|
|
405
411
|
elif any(item["project_type"] == "mobile" for item in framework_details): project_type = "mobile"
|
|
406
412
|
elif any(item["kind"] == "frontend" for item in framework_details) and any(item["kind"] == "backend" for item in framework_details): project_type = "fullstack"
|
|
413
|
+
elif any(item["project_type"] == "web-app" for item in framework_details): project_type = "web-app"
|
|
407
414
|
elif any(item["kind"] == "backend" for item in framework_details): project_type = "api"
|
|
408
415
|
elif any(item["kind"] == "frontend" for item in framework_details): project_type = "web-app"
|
|
409
416
|
elif Path("package.json").exists() and pkg.get("bin"): project_type = "cli"
|
|
@@ -539,13 +546,24 @@ These detections were inferred from the current codebase during `init --scan`:
|
|
|
539
546
|
# Generated by thachvd-kit init wizard on {datetime.now().strftime('%Y-%m-%d')}
|
|
540
547
|
# Edit freely — this is your project's brain.
|
|
541
548
|
|
|
542
|
-
## Project
|
|
543
|
-
|
|
544
|
-
- **Name:** {data['project_name']}
|
|
545
|
-
- **Description:** {data['description']}
|
|
546
|
-
- **Type:** {data['project_type']}
|
|
547
|
-
|
|
548
|
-
---
|
|
549
|
+
## Project
|
|
550
|
+
|
|
551
|
+
- **Name:** {data['project_name']}
|
|
552
|
+
- **Description:** {data['description']}
|
|
553
|
+
- **Type:** {data['project_type']}
|
|
554
|
+
|
|
555
|
+
---
|
|
556
|
+
|
|
557
|
+
## Context Status
|
|
558
|
+
|
|
559
|
+
```yaml
|
|
560
|
+
context:
|
|
561
|
+
status: {data.get('context_status', 'baseline')}
|
|
562
|
+
needs_ai_refinement: {'true' if data.get('needs_ai_refinement') else 'false'}
|
|
563
|
+
last_refined_at: {data.get('last_refined_at', 'not-yet-refined')}
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
---
|
|
549
567
|
|
|
550
568
|
## Stack
|
|
551
569
|
|
|
@@ -699,6 +717,19 @@ When done, summarize:
|
|
|
699
717
|
- what is still inferred
|
|
700
718
|
- which files provided the strongest evidence
|
|
701
719
|
"""
|
|
720
|
+
|
|
721
|
+
def format_scan_preview_lines(scanned):
|
|
722
|
+
return [
|
|
723
|
+
("Project type", scanned.get("project_type", "unknown")),
|
|
724
|
+
("Primary language", scanned.get("primary_language", "unknown")),
|
|
725
|
+
("Frameworks", ", ".join(scanned.get("frameworks", [])) or "no framework"),
|
|
726
|
+
("Database", scanned.get("database", "none")),
|
|
727
|
+
("Package manager", scanned.get("package_manager", "auto-detect")),
|
|
728
|
+
("Test framework", scanned.get("test_framework", "auto-detect")),
|
|
729
|
+
("Cloud", scanned.get("cloud", "none")),
|
|
730
|
+
("Infrastructure", ", ".join(scanned.get("infrastructure", [])) or "none"),
|
|
731
|
+
("CI/CD", scanned.get("ci_cd", "none")),
|
|
732
|
+
]
|
|
702
733
|
|
|
703
734
|
# ─── Main wizard ─────────────────────────────────────────────────────────────
|
|
704
735
|
|
|
@@ -739,8 +770,10 @@ def main():
|
|
|
739
770
|
review_scanned_fields = not use_scan
|
|
740
771
|
if use_scan:
|
|
741
772
|
print(f" {dim('Scan mode: detecting stack from current project files...')}")
|
|
742
|
-
print(f" {bold('
|
|
743
|
-
|
|
773
|
+
print(f" {bold('Detected context:')}")
|
|
774
|
+
for label, value in format_scan_preview_lines(scanned):
|
|
775
|
+
print(f" · {label}: {value}")
|
|
776
|
+
print()
|
|
744
777
|
if scanned.get("scan_evidence"):
|
|
745
778
|
print(f" {bold('Evidence:')}")
|
|
746
779
|
for line in scanned["scan_evidence"]:
|
|
@@ -830,6 +863,9 @@ def main():
|
|
|
830
863
|
data["code_style"] = data.get("code_style", (scanned or {}).get("code_style", "project-standard"))
|
|
831
864
|
data["framework_details"] = data.get("framework_details", (scanned or {}).get("framework_details", []))
|
|
832
865
|
data["scan_evidence"] = data.get("scan_evidence", (scanned or {}).get("scan_evidence", []))
|
|
866
|
+
data["context_status"] = data.get("context_status", "baseline")
|
|
867
|
+
data["needs_ai_refinement"] = data.get("needs_ai_refinement", False)
|
|
868
|
+
data["last_refined_at"] = data.get("last_refined_at", "not-yet-refined")
|
|
833
869
|
data["architecture_notes"] = data.get("architecture_notes", (scanned or {}).get("architecture_notes", "<!-- Add notes -->"))
|
|
834
870
|
data["current_phase"] = data.get("current_phase", (scanned or {}).get("current_phase", "Initial setup"))
|
|
835
871
|
data["next_phase"] = data.get("next_phase", (scanned or {}).get("next_phase", "—"))
|
|
@@ -838,6 +874,9 @@ def main():
|
|
|
838
874
|
if data["uses_docker"]: data["infrastructure"].append("docker")
|
|
839
875
|
if data["cloud"] != "none": data["infrastructure"].append(data["cloud"])
|
|
840
876
|
|
|
877
|
+
if not args.yes:
|
|
878
|
+
data["needs_ai_refinement"] = ask_bool("Should the agent refine PROJECT_CONTEXT.md on first session start?", default=use_scan)
|
|
879
|
+
|
|
841
880
|
# ── Generate files ────────────────────────────────────────────────────
|
|
842
881
|
section("Generating Files")
|
|
843
882
|
|
|
@@ -853,7 +892,7 @@ def main():
|
|
|
853
892
|
print(f" {green('✓')} {bold('CLAUDE.md')} generated (Claude Code / Codex)")
|
|
854
893
|
|
|
855
894
|
ai_refine_path = None
|
|
856
|
-
if
|
|
895
|
+
if data.get("needs_ai_refinement"):
|
|
857
896
|
ai_refine_path = Path("AI_CONTEXT_REFINEMENT.md")
|
|
858
897
|
ai_refine_path.write_text(generate_ai_context_refinement_prompt(data), encoding="utf-8")
|
|
859
898
|
print(f" {green('✓')} {bold('AI_CONTEXT_REFINEMENT.md')} generated")
|