aioengine 0.1.0 → 0.1.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/package.json +1 -1
- package/src/index.js +152 -131
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -5,13 +5,14 @@ import pc from "picocolors";
|
|
|
5
5
|
import fs from "node:fs";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import { execSync } from "node:child_process";
|
|
8
|
+
import { fileURLToPath } from "node:url";
|
|
8
9
|
|
|
9
10
|
const program = new Command();
|
|
10
11
|
|
|
11
12
|
program
|
|
12
13
|
.name("aioengine")
|
|
13
14
|
.description("AI change control for developers using AI coding tools.")
|
|
14
|
-
.version(
|
|
15
|
+
.version(getCliVersion());
|
|
15
16
|
|
|
16
17
|
program
|
|
17
18
|
.command("init")
|
|
@@ -438,34 +439,96 @@ function getChangedFiles(root) {
|
|
|
438
439
|
}
|
|
439
440
|
|
|
440
441
|
function inferTaskProfile(task) {
|
|
441
|
-
const
|
|
442
|
+
const cleanTask = task.toLowerCase();
|
|
442
443
|
|
|
443
444
|
const profiles = [
|
|
444
|
-
|
|
445
|
+
{
|
|
446
|
+
id: "ui",
|
|
447
|
+
label: "UI / frontend task",
|
|
448
|
+
strongKeywords: [
|
|
449
|
+
"landing page",
|
|
450
|
+
"home page",
|
|
451
|
+
"hero",
|
|
452
|
+
"headline",
|
|
453
|
+
"cta",
|
|
454
|
+
"navbar",
|
|
455
|
+
"footer",
|
|
456
|
+
"layout",
|
|
457
|
+
"mobile",
|
|
458
|
+
"responsive",
|
|
459
|
+
"pricing page",
|
|
460
|
+
"dashboard header",
|
|
461
|
+
],
|
|
462
|
+
keywords: [
|
|
463
|
+
"ui",
|
|
464
|
+
"frontend",
|
|
465
|
+
"front end",
|
|
466
|
+
"page",
|
|
467
|
+
"component",
|
|
468
|
+
"style",
|
|
469
|
+
"css",
|
|
470
|
+
"tailwind",
|
|
471
|
+
"design",
|
|
472
|
+
"copy",
|
|
473
|
+
"button",
|
|
474
|
+
"card",
|
|
475
|
+
"section",
|
|
476
|
+
],
|
|
477
|
+
allowed: [
|
|
478
|
+
"src/app/",
|
|
479
|
+
"src/components/",
|
|
480
|
+
"src/siteconfig.ts",
|
|
481
|
+
"public/",
|
|
482
|
+
"next-env.d.ts",
|
|
483
|
+
],
|
|
484
|
+
sensitive: [
|
|
485
|
+
".env",
|
|
486
|
+
"auth",
|
|
487
|
+
"stripe",
|
|
488
|
+
"billing",
|
|
489
|
+
"payment",
|
|
490
|
+
"supabase",
|
|
491
|
+
"migration",
|
|
492
|
+
"middleware",
|
|
493
|
+
"package.json",
|
|
494
|
+
".github/workflows",
|
|
495
|
+
],
|
|
496
|
+
},
|
|
497
|
+
{
|
|
445
498
|
id: "cli",
|
|
446
499
|
label: "CLI / tooling task",
|
|
447
|
-
|
|
500
|
+
strongKeywords: [
|
|
448
501
|
"cli",
|
|
449
502
|
"command",
|
|
503
|
+
"terminal command",
|
|
504
|
+
"npm package",
|
|
505
|
+
"package executable",
|
|
506
|
+
"bin",
|
|
507
|
+
"commander",
|
|
508
|
+
"aioengine init",
|
|
509
|
+
"aioengine check",
|
|
510
|
+
"aioengine review",
|
|
511
|
+
"aioengine scope",
|
|
512
|
+
"aioengine rules",
|
|
513
|
+
],
|
|
514
|
+
keywords: [
|
|
450
515
|
"terminal",
|
|
451
516
|
"init",
|
|
452
517
|
"check",
|
|
453
518
|
"review",
|
|
454
519
|
"scope",
|
|
455
520
|
"rules",
|
|
456
|
-
"package",
|
|
457
521
|
"script",
|
|
458
522
|
"npm",
|
|
459
|
-
"
|
|
460
|
-
"
|
|
461
|
-
"
|
|
523
|
+
"package",
|
|
524
|
+
"developer tool",
|
|
525
|
+
"tooling",
|
|
526
|
+
"publish",
|
|
462
527
|
],
|
|
463
528
|
allowed: [
|
|
464
529
|
"packages/cli/",
|
|
465
530
|
"package.json",
|
|
466
531
|
"package-lock.json",
|
|
467
|
-
"src/index.js",
|
|
468
|
-
"readme",
|
|
469
532
|
".aioengine/",
|
|
470
533
|
"CLAUDE.md",
|
|
471
534
|
".cursor/",
|
|
@@ -482,179 +545,124 @@ function inferTaskProfile(task) {
|
|
|
482
545
|
".github/workflows",
|
|
483
546
|
],
|
|
484
547
|
},
|
|
485
|
-
{
|
|
486
|
-
id: "ui",
|
|
487
|
-
label: "UI / frontend task",
|
|
488
|
-
keywords: [
|
|
489
|
-
"ui",
|
|
490
|
-
"layout",
|
|
491
|
-
"style",
|
|
492
|
-
"design",
|
|
493
|
-
"button",
|
|
494
|
-
"card",
|
|
495
|
-
"page",
|
|
496
|
-
"copy",
|
|
497
|
-
"text",
|
|
498
|
-
"color",
|
|
499
|
-
"colour",
|
|
500
|
-
"spacing",
|
|
501
|
-
"responsive",
|
|
502
|
-
"navbar",
|
|
503
|
-
"footer",
|
|
504
|
-
"hero",
|
|
505
|
-
"landing",
|
|
506
|
-
"pricing",
|
|
507
|
-
"headline",
|
|
508
|
-
],
|
|
509
|
-
allowed: [
|
|
510
|
-
"app/",
|
|
511
|
-
"pages/",
|
|
512
|
-
"components/",
|
|
513
|
-
"styles/",
|
|
514
|
-
"public/",
|
|
515
|
-
"src/app/",
|
|
516
|
-
"src/components/",
|
|
517
|
-
"src/styles/",
|
|
518
|
-
".css",
|
|
519
|
-
".tsx",
|
|
520
|
-
".jsx",
|
|
521
|
-
],
|
|
522
|
-
sensitive: [
|
|
523
|
-
"api/",
|
|
524
|
-
"auth",
|
|
525
|
-
"session",
|
|
526
|
-
"stripe",
|
|
527
|
-
"billing",
|
|
528
|
-
"payment",
|
|
529
|
-
"supabase",
|
|
530
|
-
"migration",
|
|
531
|
-
"schema",
|
|
532
|
-
"rls",
|
|
533
|
-
".env",
|
|
534
|
-
"package.json",
|
|
535
|
-
"package-lock.json",
|
|
536
|
-
"middleware",
|
|
537
|
-
".github/workflows",
|
|
538
|
-
"next.config",
|
|
539
|
-
"vercel",
|
|
540
|
-
],
|
|
541
|
-
},
|
|
542
548
|
{
|
|
543
549
|
id: "docs",
|
|
544
550
|
label: "Docs / copy task",
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
"copy",
|
|
549
|
-
"text",
|
|
550
|
-
"wording",
|
|
551
|
-
"content",
|
|
552
|
-
"landing page copy",
|
|
553
|
-
"headline",
|
|
554
|
-
"description",
|
|
555
|
-
],
|
|
556
|
-
allowed: [
|
|
557
|
-
".md",
|
|
558
|
-
"readme",
|
|
559
|
-
"app/",
|
|
560
|
-
"src/app/",
|
|
561
|
-
"components/",
|
|
562
|
-
"src/components/",
|
|
563
|
-
],
|
|
551
|
+
strongKeywords: ["readme", "documentation", "docs"],
|
|
552
|
+
keywords: ["copy", "text", "wording", "content", "instructions"],
|
|
553
|
+
allowed: ["README", "readme", "docs/", ".md", "CLAUDE.md"],
|
|
564
554
|
sensitive: [
|
|
565
|
-
"
|
|
555
|
+
".env",
|
|
566
556
|
"auth",
|
|
567
557
|
"stripe",
|
|
568
558
|
"billing",
|
|
569
559
|
"payment",
|
|
570
560
|
"supabase",
|
|
571
561
|
"migration",
|
|
572
|
-
".env",
|
|
573
|
-
"package.json",
|
|
574
562
|
"middleware",
|
|
563
|
+
"package.json",
|
|
575
564
|
],
|
|
576
565
|
},
|
|
577
566
|
{
|
|
578
567
|
id: "backend",
|
|
579
568
|
label: "Backend / API task",
|
|
569
|
+
strongKeywords: ["api route", "route handler", "database", "server action"],
|
|
580
570
|
keywords: [
|
|
581
571
|
"api",
|
|
582
|
-
"route",
|
|
583
|
-
"server",
|
|
584
572
|
"backend",
|
|
573
|
+
"server",
|
|
585
574
|
"database",
|
|
586
575
|
"supabase",
|
|
576
|
+
"schema",
|
|
577
|
+
"auth",
|
|
587
578
|
"webhook",
|
|
588
579
|
"stripe",
|
|
589
|
-
"auth",
|
|
590
|
-
"login",
|
|
591
|
-
"billing",
|
|
592
580
|
],
|
|
593
581
|
allowed: [
|
|
594
|
-
"api/",
|
|
595
|
-
"server",
|
|
596
|
-
"lib/",
|
|
582
|
+
"src/app/api/",
|
|
597
583
|
"src/lib/",
|
|
598
|
-
"supabase",
|
|
599
|
-
"
|
|
600
|
-
"migration",
|
|
601
|
-
"middleware",
|
|
584
|
+
"supabase/",
|
|
585
|
+
"prisma/",
|
|
602
586
|
"package.json",
|
|
603
587
|
],
|
|
604
|
-
sensitive: [".env", "billing", "payment", "stripe", "auth", "rls", "migration"],
|
|
605
|
-
},
|
|
606
|
-
];
|
|
607
|
-
|
|
608
|
-
const matched = profiles.find((profile) =>
|
|
609
|
-
profile.keywords.some((keyword) => lower.includes(keyword))
|
|
610
|
-
);
|
|
611
|
-
|
|
612
|
-
return (
|
|
613
|
-
matched ?? {
|
|
614
|
-
id: "unknown",
|
|
615
|
-
label: "Unknown / general task",
|
|
616
|
-
keywords: [],
|
|
617
|
-
allowed: [],
|
|
618
588
|
sensitive: [
|
|
619
589
|
".env",
|
|
620
|
-
"auth",
|
|
621
|
-
"session",
|
|
622
590
|
"stripe",
|
|
623
591
|
"billing",
|
|
624
592
|
"payment",
|
|
625
|
-
"
|
|
593
|
+
"auth",
|
|
626
594
|
"migration",
|
|
627
595
|
"schema",
|
|
628
596
|
"rls",
|
|
629
597
|
"middleware",
|
|
630
|
-
"package.json",
|
|
631
|
-
"package-lock.json",
|
|
632
|
-
".github/workflows",
|
|
633
598
|
],
|
|
599
|
+
},
|
|
600
|
+
];
|
|
601
|
+
|
|
602
|
+
const scoredProfiles = profiles
|
|
603
|
+
.map((profile) => {
|
|
604
|
+
const strongScore = profile.strongKeywords.filter((keyword) =>
|
|
605
|
+
cleanTask.includes(keyword)
|
|
606
|
+
).length;
|
|
607
|
+
|
|
608
|
+
const normalScore = profile.keywords.filter((keyword) =>
|
|
609
|
+
cleanTask.includes(keyword)
|
|
610
|
+
).length;
|
|
611
|
+
|
|
612
|
+
return {
|
|
613
|
+
...profile,
|
|
614
|
+
score: strongScore * 3 + normalScore,
|
|
615
|
+
};
|
|
616
|
+
})
|
|
617
|
+
.filter((profile) => profile.score > 0)
|
|
618
|
+
.sort((a, b) => b.score - a.score);
|
|
619
|
+
|
|
620
|
+
return (
|
|
621
|
+
scoredProfiles[0] ?? {
|
|
622
|
+
id: "unknown",
|
|
623
|
+
label: "Unknown / general task",
|
|
624
|
+
allowed: [],
|
|
625
|
+
sensitive: [],
|
|
634
626
|
}
|
|
635
627
|
);
|
|
636
628
|
}
|
|
637
629
|
|
|
638
630
|
function isProbablyOutOfScope(file, profile) {
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
if (profile.id === "unknown") {
|
|
631
|
+
if (!profile || profile.id === "unknown") {
|
|
642
632
|
return false;
|
|
643
633
|
}
|
|
644
634
|
|
|
645
|
-
const
|
|
646
|
-
|
|
647
|
-
|
|
635
|
+
const normalizedFile = file.replaceAll("\\", "/").toLowerCase();
|
|
636
|
+
|
|
637
|
+
const allowedPatterns = profile.allowed ?? [];
|
|
638
|
+
const sensitivePatterns = profile.sensitive ?? [];
|
|
639
|
+
|
|
640
|
+
const isAllowed = allowedPatterns.some((pattern) => {
|
|
641
|
+
const normalizedPattern = pattern.replaceAll("\\", "/").toLowerCase();
|
|
642
|
+
|
|
643
|
+
if (normalizedPattern.endsWith("/")) {
|
|
644
|
+
return normalizedFile.startsWith(normalizedPattern);
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
return (
|
|
648
|
+
normalizedFile === normalizedPattern ||
|
|
649
|
+
normalizedFile.includes(normalizedPattern)
|
|
650
|
+
);
|
|
651
|
+
});
|
|
648
652
|
|
|
649
|
-
if (
|
|
653
|
+
if (isAllowed) {
|
|
650
654
|
return false;
|
|
651
655
|
}
|
|
652
656
|
|
|
653
|
-
const
|
|
654
|
-
|
|
657
|
+
const isSensitive = sensitivePatterns.some((pattern) =>
|
|
658
|
+
normalizedFile.includes(pattern.toLowerCase())
|
|
655
659
|
);
|
|
656
660
|
|
|
657
|
-
|
|
661
|
+
if (isSensitive) {
|
|
662
|
+
return true;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
return allowedPatterns.length > 0;
|
|
658
666
|
}
|
|
659
667
|
|
|
660
668
|
function isRiskyFile(file) {
|
|
@@ -887,4 +895,17 @@ Do not add dependencies without a clear reason.
|
|
|
887
895
|
|
|
888
896
|
For UI-only tasks, avoid backend, API, database, and config changes.
|
|
889
897
|
`;
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
function getCliVersion() {
|
|
901
|
+
try {
|
|
902
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
903
|
+
const currentDir = path.dirname(currentFile);
|
|
904
|
+
const packagePath = path.join(currentDir, "..", "package.json");
|
|
905
|
+
const packageJson = JSON.parse(fs.readFileSync(packagePath, "utf8"));
|
|
906
|
+
|
|
907
|
+
return packageJson.version ?? "0.0.0";
|
|
908
|
+
} catch {
|
|
909
|
+
return "0.0.0";
|
|
910
|
+
}
|
|
890
911
|
}
|