@champpaba/claude-agent-kit 2.6.0 ā 2.8.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/.claude/CLAUDE.md +152 -58
- package/.claude/agents/02-uxui-frontend.md +5 -6
- package/.claude/agents/07-ux-tester.md +407 -0
- package/.claude/commands/cdev.md +113 -8
- package/.claude/commands/csetup.md +377 -51
- package/.claude/commands/designsetup.md +171 -48
- package/.claude/commands/extract.md +382 -668
- package/.claude/commands/pageplan.md +25 -27
- package/.claude/contexts/design/box-thinking.md +4 -4
- package/.claude/contexts/design/color-theory.md +5 -5
- package/.claude/contexts/design/index.md +9 -9
- package/.claude/contexts/design/spacing.md +4 -4
- package/.claude/contexts/patterns/agent-discovery.md +1 -1
- package/.claude/contexts/patterns/animation-patterns.md +3 -3
- package/.claude/contexts/patterns/ui-component-consistency.md +3 -3
- package/.claude/lib/README.md +1 -1
- package/.claude/lib/agent-executor.md +223 -0
- package/.claude/lib/context-loading-protocol.md +5 -6
- package/.claude/lib/detailed-guides/agent-system.md +4 -4
- package/.claude/lib/detailed-guides/best-practices-system.md +5 -4
- package/.claude/lib/detailed-guides/context-optimization.md +21 -22
- package/.claude/lib/detailed-guides/design-system.md +6 -5
- package/.claude/lib/detailed-guides/page-planning.md +6 -6
- package/.claude/lib/document-loader.md +32 -47
- package/.claude/lib/task-analyzer.md +194 -1
- package/.claude/templates/PROJECT_STATUS.template.yml +1 -1
- package/.claude/templates/STYLE_GUIDE.template.md +7 -7
- package/.claude/templates/design-context-template.md +22 -29
- package/.claude/templates/page-plan-example.md +9 -9
- package/.claude/templates/phases-sections/ux-testing.md +164 -0
- package/README.md +28 -1
- package/package.json +8 -4
|
@@ -179,18 +179,18 @@ let pageType = 'generic'
|
|
|
179
179
|
if (hasFrontend) {
|
|
180
180
|
output(`\nšØ UI work detected - validating design system...`)
|
|
181
181
|
|
|
182
|
-
const tokensPath = 'design-system/
|
|
183
|
-
const
|
|
182
|
+
const tokensPath = 'design-system/data.yaml' // v2.0 tokens
|
|
183
|
+
const readmePath = 'design-system/README.md'
|
|
184
184
|
const pagePlanPath = `openspec/changes/${changeId}/page-plan.md`
|
|
185
185
|
|
|
186
186
|
const hasTokens = fileExists(tokensPath)
|
|
187
|
-
const
|
|
187
|
+
const hasReadme = fileExists(readmePath)
|
|
188
188
|
const hasPagePlan = fileExists(pagePlanPath)
|
|
189
189
|
|
|
190
|
-
// ========== LOAD
|
|
190
|
+
// ========== LOAD data.yaml (v2.0 structure) ==========
|
|
191
191
|
if (hasTokens) {
|
|
192
|
-
tokens =
|
|
193
|
-
output(`ā
|
|
192
|
+
tokens = parseYaml(Read(tokensPath))
|
|
193
|
+
output(`ā
data.yaml Loaded:`)
|
|
194
194
|
output(` - Style: ${tokens.style.name}`)
|
|
195
195
|
output(` - Theme: ${tokens.theme.name}`)
|
|
196
196
|
output(` - Animations: ${tokens.animations.enabled ? 'Enabled' : 'Disabled'}`)
|
|
@@ -212,13 +212,13 @@ if (hasFrontend) {
|
|
|
212
212
|
output(` ā Run /pageplan first for better component planning`)
|
|
213
213
|
}
|
|
214
214
|
|
|
215
|
-
if (!hasTokens || !
|
|
215
|
+
if (!hasTokens || !hasReadme) {
|
|
216
216
|
warn(`
|
|
217
217
|
ā ļø WARNING: UI work detected but design system incomplete!
|
|
218
218
|
|
|
219
219
|
Found:
|
|
220
|
-
${
|
|
221
|
-
${hasTokens ? 'ā
' : 'ā'}
|
|
220
|
+
${hasReadme ? 'ā
' : 'ā'} README.md (human-readable)
|
|
221
|
+
${hasTokens ? 'ā
' : 'ā'} data.yaml
|
|
222
222
|
${hasPagePlan ? 'ā
' : 'ā'} page-plan.md
|
|
223
223
|
|
|
224
224
|
This may result in:
|
|
@@ -240,8 +240,8 @@ Continue anyway? (yes/no)
|
|
|
240
240
|
}
|
|
241
241
|
} else {
|
|
242
242
|
output(`ā
Design System Ready`)
|
|
243
|
-
output(` -
|
|
244
|
-
output(` -
|
|
243
|
+
output(` - README.md ā (human-readable)`)
|
|
244
|
+
output(` - data.yaml ā`)
|
|
245
245
|
if (hasPagePlan) output(` - page-plan.md ā`)
|
|
246
246
|
}
|
|
247
247
|
}
|
|
@@ -316,9 +316,9 @@ for (const layer of requiredLayers) {
|
|
|
316
316
|
}
|
|
317
317
|
|
|
318
318
|
// 5. Check for conflicts with design system (if exists)
|
|
319
|
-
const tokensPath = 'design-system/
|
|
319
|
+
const tokensPath = 'design-system/data.yaml'
|
|
320
320
|
if (fileExists(tokensPath) && researchResults.length > 0) {
|
|
321
|
-
const tokens =
|
|
321
|
+
const tokens = parseYaml(Read(tokensPath))
|
|
322
322
|
const conflicts = checkDesignConflicts(tokens, researchResults, changeAnalysis)
|
|
323
323
|
|
|
324
324
|
if (conflicts.length > 0) {
|
|
@@ -687,6 +687,7 @@ function executeLayerResearch(layer, changeAnalysis) {
|
|
|
687
687
|
findings: [],
|
|
688
688
|
recommendations: [],
|
|
689
689
|
warnings: [],
|
|
690
|
+
requiredItems: [], // Critical checklist items that MUST be addressed
|
|
690
691
|
source: 'claude-knowledge'
|
|
691
692
|
}
|
|
692
693
|
|
|
@@ -706,9 +707,325 @@ function executeLayerResearch(layer, changeAnalysis) {
|
|
|
706
707
|
result.recommendations = generateRecommendations(layer, changeAnalysis)
|
|
707
708
|
result.warnings = checkForWarnings(layer, changeAnalysis)
|
|
708
709
|
|
|
710
|
+
// Inject critical required items based on layer and context
|
|
711
|
+
// WHY: These are non-negotiable security/compliance requirements
|
|
712
|
+
result.requiredItems = injectCriticalRequiredItems(layer, changeAnalysis)
|
|
713
|
+
|
|
709
714
|
return result
|
|
710
715
|
}
|
|
711
716
|
|
|
717
|
+
// ============================================================
|
|
718
|
+
// CRITICAL FLOW REQUIREMENTS (v2.8.0)
|
|
719
|
+
// ============================================================
|
|
720
|
+
// These are non-negotiable items that MUST be in the checklist
|
|
721
|
+
// WHY: Security/compliance failures have legal/financial consequences
|
|
722
|
+
|
|
723
|
+
/**
|
|
724
|
+
* Inject critical required items based on layer type and change context
|
|
725
|
+
* Returns checklist items that agents MUST verify are implemented
|
|
726
|
+
*/
|
|
727
|
+
function injectCriticalRequiredItems(layer, changeAnalysis) {
|
|
728
|
+
const items = []
|
|
729
|
+
|
|
730
|
+
// Security Requirements Layer
|
|
731
|
+
if (layer.name === 'Security Requirements') {
|
|
732
|
+
// Auth-related critical items
|
|
733
|
+
if (changeAnalysis.hasAuth) {
|
|
734
|
+
items.push(...CRITICAL_FLOWS.auth.security)
|
|
735
|
+
}
|
|
736
|
+
// Payment-related critical items
|
|
737
|
+
if (changeAnalysis.hasPayment) {
|
|
738
|
+
items.push(...CRITICAL_FLOWS.payment.security)
|
|
739
|
+
}
|
|
740
|
+
// Sensitive data handling
|
|
741
|
+
if (changeAnalysis.hasSensitiveData) {
|
|
742
|
+
items.push(...CRITICAL_FLOWS.sensitiveData.security)
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
// Compliance Layer
|
|
747
|
+
if (layer.name.includes('Compliance')) {
|
|
748
|
+
if (changeAnalysis.industryContext === 'healthcare') {
|
|
749
|
+
items.push(...CRITICAL_FLOWS.healthcare.compliance)
|
|
750
|
+
}
|
|
751
|
+
if (changeAnalysis.industryContext === 'fintech') {
|
|
752
|
+
items.push(...CRITICAL_FLOWS.fintech.compliance)
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
// Data Architecture Layer
|
|
757
|
+
if (layer.name === 'Data Architecture') {
|
|
758
|
+
if (changeAnalysis.hasSensitiveData) {
|
|
759
|
+
items.push(...CRITICAL_FLOWS.sensitiveData.dataArchitecture)
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
return items
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
/**
|
|
767
|
+
* Critical Flow Definitions
|
|
768
|
+
* Format: { category: { layer: [...items] } }
|
|
769
|
+
* Each item has: id, check, why, severity
|
|
770
|
+
*/
|
|
771
|
+
const CRITICAL_FLOWS = {
|
|
772
|
+
// ============================================================
|
|
773
|
+
// AUTH CRITICAL FLOWS
|
|
774
|
+
// ============================================================
|
|
775
|
+
auth: {
|
|
776
|
+
security: [
|
|
777
|
+
{
|
|
778
|
+
id: 'auth-password-hash',
|
|
779
|
+
check: 'ā Password hashing with bcrypt/argon2 (cost factor ā„ 10)',
|
|
780
|
+
why: 'Plain text or weak hashing = immediate breach if DB leaked',
|
|
781
|
+
severity: 'critical'
|
|
782
|
+
},
|
|
783
|
+
{
|
|
784
|
+
id: 'auth-rate-limit',
|
|
785
|
+
check: 'ā Rate limiting on login (max 5 attempts per 15 min)',
|
|
786
|
+
why: 'Prevents brute force attacks',
|
|
787
|
+
severity: 'critical'
|
|
788
|
+
},
|
|
789
|
+
{
|
|
790
|
+
id: 'auth-session-timeout',
|
|
791
|
+
check: 'ā Session timeout configured (⤠24h, ⤠15min for sensitive)',
|
|
792
|
+
why: 'Abandoned sessions are attack vectors',
|
|
793
|
+
severity: 'high'
|
|
794
|
+
},
|
|
795
|
+
{
|
|
796
|
+
id: 'auth-csrf',
|
|
797
|
+
check: 'ā CSRF protection on all state-changing endpoints',
|
|
798
|
+
why: 'OWASP Top 10 vulnerability',
|
|
799
|
+
severity: 'critical'
|
|
800
|
+
},
|
|
801
|
+
{
|
|
802
|
+
id: 'auth-secure-cookies',
|
|
803
|
+
check: 'ā Cookies: httpOnly, secure, sameSite=strict',
|
|
804
|
+
why: 'Prevents XSS token theft and CSRF',
|
|
805
|
+
severity: 'critical'
|
|
806
|
+
},
|
|
807
|
+
{
|
|
808
|
+
id: 'auth-password-policy',
|
|
809
|
+
check: 'ā Password policy enforced (min 8 chars, complexity optional)',
|
|
810
|
+
why: 'Weak passwords are #1 breach cause',
|
|
811
|
+
severity: 'high'
|
|
812
|
+
},
|
|
813
|
+
{
|
|
814
|
+
id: 'auth-account-lockout',
|
|
815
|
+
check: 'ā Account lockout after repeated failures (with unlock mechanism)',
|
|
816
|
+
why: 'Prevents brute force, but needs recovery path',
|
|
817
|
+
severity: 'medium'
|
|
818
|
+
}
|
|
819
|
+
],
|
|
820
|
+
flow: [
|
|
821
|
+
{
|
|
822
|
+
id: 'auth-flow-login',
|
|
823
|
+
check: 'ā Login flow: input ā validate ā session ā redirect',
|
|
824
|
+
why: 'Standard secure login pattern',
|
|
825
|
+
severity: 'high'
|
|
826
|
+
},
|
|
827
|
+
{
|
|
828
|
+
id: 'auth-flow-logout',
|
|
829
|
+
check: 'ā Logout: invalidate session server-side (not just cookie)',
|
|
830
|
+
why: 'Client-side only logout leaves session valid',
|
|
831
|
+
severity: 'high'
|
|
832
|
+
},
|
|
833
|
+
{
|
|
834
|
+
id: 'auth-flow-forgot',
|
|
835
|
+
check: 'ā Forgot password: email ā time-limited token ā reset',
|
|
836
|
+
why: 'Token must expire (⤠1 hour)',
|
|
837
|
+
severity: 'high'
|
|
838
|
+
}
|
|
839
|
+
]
|
|
840
|
+
},
|
|
841
|
+
|
|
842
|
+
// ============================================================
|
|
843
|
+
// PAYMENT CRITICAL FLOWS
|
|
844
|
+
// ============================================================
|
|
845
|
+
payment: {
|
|
846
|
+
security: [
|
|
847
|
+
{
|
|
848
|
+
id: 'payment-no-card-storage',
|
|
849
|
+
check: 'ā NO raw card numbers stored (use Stripe/payment provider tokens)',
|
|
850
|
+
why: 'PCI-DSS requirement, storing cards = massive liability',
|
|
851
|
+
severity: 'critical'
|
|
852
|
+
},
|
|
853
|
+
{
|
|
854
|
+
id: 'payment-https',
|
|
855
|
+
check: 'ā HTTPS enforced on all payment pages',
|
|
856
|
+
why: 'Payment data in transit must be encrypted',
|
|
857
|
+
severity: 'critical'
|
|
858
|
+
},
|
|
859
|
+
{
|
|
860
|
+
id: 'payment-webhook-verify',
|
|
861
|
+
check: 'ā Webhook signature verification (never trust unverified webhooks)',
|
|
862
|
+
why: 'Attackers can fake payment success webhooks',
|
|
863
|
+
severity: 'critical'
|
|
864
|
+
},
|
|
865
|
+
{
|
|
866
|
+
id: 'payment-idempotency',
|
|
867
|
+
check: 'ā Idempotency keys for payment creation',
|
|
868
|
+
why: 'Prevents double charges on retry',
|
|
869
|
+
severity: 'high'
|
|
870
|
+
},
|
|
871
|
+
{
|
|
872
|
+
id: 'payment-amount-verify',
|
|
873
|
+
check: 'ā Server-side price verification (never trust client price)',
|
|
874
|
+
why: 'Attackers modify client-side prices',
|
|
875
|
+
severity: 'critical'
|
|
876
|
+
}
|
|
877
|
+
],
|
|
878
|
+
flow: [
|
|
879
|
+
{
|
|
880
|
+
id: 'payment-flow-checkout',
|
|
881
|
+
check: 'ā Checkout flow: cart ā address ā payment ā confirm ā receipt',
|
|
882
|
+
why: 'Standard e-commerce pattern users expect',
|
|
883
|
+
severity: 'medium'
|
|
884
|
+
},
|
|
885
|
+
{
|
|
886
|
+
id: 'payment-flow-error',
|
|
887
|
+
check: 'ā Payment error handling with clear user message',
|
|
888
|
+
why: 'Failed payments need recovery path',
|
|
889
|
+
severity: 'high'
|
|
890
|
+
},
|
|
891
|
+
{
|
|
892
|
+
id: 'payment-flow-refund',
|
|
893
|
+
check: 'ā Refund flow documented (even if manual)',
|
|
894
|
+
why: 'Legal requirement in most jurisdictions',
|
|
895
|
+
severity: 'high'
|
|
896
|
+
}
|
|
897
|
+
]
|
|
898
|
+
},
|
|
899
|
+
|
|
900
|
+
// ============================================================
|
|
901
|
+
// SENSITIVE DATA CRITICAL FLOWS
|
|
902
|
+
// ============================================================
|
|
903
|
+
sensitiveData: {
|
|
904
|
+
security: [
|
|
905
|
+
{
|
|
906
|
+
id: 'data-encryption-rest',
|
|
907
|
+
check: 'ā Encryption at rest for PII/PHI (AES-256 or DB-level)',
|
|
908
|
+
why: 'Breached DB without encryption = full exposure',
|
|
909
|
+
severity: 'critical'
|
|
910
|
+
},
|
|
911
|
+
{
|
|
912
|
+
id: 'data-encryption-transit',
|
|
913
|
+
check: 'ā Encryption in transit (TLS 1.2+)',
|
|
914
|
+
why: 'Data interception prevention',
|
|
915
|
+
severity: 'critical'
|
|
916
|
+
},
|
|
917
|
+
{
|
|
918
|
+
id: 'data-access-logging',
|
|
919
|
+
check: 'ā Audit logging for sensitive data access',
|
|
920
|
+
why: 'Required for breach investigation and compliance',
|
|
921
|
+
severity: 'high'
|
|
922
|
+
},
|
|
923
|
+
{
|
|
924
|
+
id: 'data-minimization',
|
|
925
|
+
check: 'ā Data minimization (only collect what is needed)',
|
|
926
|
+
why: 'GDPR principle, reduces breach impact',
|
|
927
|
+
severity: 'medium'
|
|
928
|
+
}
|
|
929
|
+
],
|
|
930
|
+
dataArchitecture: [
|
|
931
|
+
{
|
|
932
|
+
id: 'data-arch-backup',
|
|
933
|
+
check: 'ā Backup strategy with encryption',
|
|
934
|
+
why: 'Backups are often unencrypted breach vector',
|
|
935
|
+
severity: 'high'
|
|
936
|
+
},
|
|
937
|
+
{
|
|
938
|
+
id: 'data-arch-retention',
|
|
939
|
+
check: 'ā Data retention policy defined',
|
|
940
|
+
why: 'Legal requirement (GDPR right to deletion)',
|
|
941
|
+
severity: 'medium'
|
|
942
|
+
}
|
|
943
|
+
]
|
|
944
|
+
},
|
|
945
|
+
|
|
946
|
+
// ============================================================
|
|
947
|
+
// HEALTHCARE COMPLIANCE (HIPAA)
|
|
948
|
+
// ============================================================
|
|
949
|
+
healthcare: {
|
|
950
|
+
compliance: [
|
|
951
|
+
{
|
|
952
|
+
id: 'hipaa-phi-encrypt',
|
|
953
|
+
check: 'ā All PHI encrypted at rest and in transit',
|
|
954
|
+
why: 'HIPAA Security Rule requirement',
|
|
955
|
+
severity: 'critical'
|
|
956
|
+
},
|
|
957
|
+
{
|
|
958
|
+
id: 'hipaa-access-control',
|
|
959
|
+
check: 'ā Role-based access control for PHI',
|
|
960
|
+
why: 'Minimum necessary standard',
|
|
961
|
+
severity: 'critical'
|
|
962
|
+
},
|
|
963
|
+
{
|
|
964
|
+
id: 'hipaa-audit-trail',
|
|
965
|
+
check: 'ā Audit trail for all PHI access (who, what, when)',
|
|
966
|
+
why: 'HIPAA requires 6-year audit log retention',
|
|
967
|
+
severity: 'critical'
|
|
968
|
+
},
|
|
969
|
+
{
|
|
970
|
+
id: 'hipaa-baa',
|
|
971
|
+
check: 'ā BAA signed with all vendors handling PHI',
|
|
972
|
+
why: 'Business Associate Agreement legally required',
|
|
973
|
+
severity: 'critical'
|
|
974
|
+
},
|
|
975
|
+
{
|
|
976
|
+
id: 'hipaa-breach-plan',
|
|
977
|
+
check: 'ā Breach notification plan documented',
|
|
978
|
+
why: '60-day notification requirement',
|
|
979
|
+
severity: 'high'
|
|
980
|
+
}
|
|
981
|
+
]
|
|
982
|
+
},
|
|
983
|
+
|
|
984
|
+
// ============================================================
|
|
985
|
+
// FINTECH COMPLIANCE (PCI-DSS)
|
|
986
|
+
// ============================================================
|
|
987
|
+
fintech: {
|
|
988
|
+
compliance: [
|
|
989
|
+
{
|
|
990
|
+
id: 'pci-no-pan',
|
|
991
|
+
check: 'ā No PAN (card numbers) stored unless PCI certified',
|
|
992
|
+
why: 'PCI-DSS Level 1 requirement',
|
|
993
|
+
severity: 'critical'
|
|
994
|
+
},
|
|
995
|
+
{
|
|
996
|
+
id: 'pci-tokenization',
|
|
997
|
+
check: 'ā Tokenization for card data (Stripe, Braintree)',
|
|
998
|
+
why: 'Removes PCI scope from your systems',
|
|
999
|
+
severity: 'critical'
|
|
1000
|
+
},
|
|
1001
|
+
{
|
|
1002
|
+
id: 'pci-network-segment',
|
|
1003
|
+
check: 'ā Network segmentation for payment systems',
|
|
1004
|
+
why: 'Limits breach blast radius',
|
|
1005
|
+
severity: 'high'
|
|
1006
|
+
},
|
|
1007
|
+
{
|
|
1008
|
+
id: 'fintech-kyc',
|
|
1009
|
+
check: 'ā KYC verification flow for financial accounts',
|
|
1010
|
+
why: 'AML/KYC regulations',
|
|
1011
|
+
severity: 'high'
|
|
1012
|
+
},
|
|
1013
|
+
{
|
|
1014
|
+
id: 'fintech-transaction-limits',
|
|
1015
|
+
check: 'ā Transaction limits and velocity checks',
|
|
1016
|
+
why: 'Fraud prevention, regulatory requirement',
|
|
1017
|
+
severity: 'high'
|
|
1018
|
+
},
|
|
1019
|
+
{
|
|
1020
|
+
id: 'fintech-audit',
|
|
1021
|
+
check: 'ā Transaction audit trail (immutable)',
|
|
1022
|
+
why: 'Regulatory reporting requirement',
|
|
1023
|
+
severity: 'critical'
|
|
1024
|
+
}
|
|
1025
|
+
]
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
|
|
712
1029
|
// Generate domain knowledge using Claude's reasoning
|
|
713
1030
|
// This is where Claude applies its training to the specific change
|
|
714
1031
|
function generateDomainKnowledge(layer, changeAnalysis) {
|
|
@@ -1221,16 +1538,18 @@ function extractPotentialLibraryNames(text: string): string[] {
|
|
|
1221
1538
|
})
|
|
1222
1539
|
|
|
1223
1540
|
// requirements.txt: sqlalchemy==2.0.0 ā sqlalchemy
|
|
1224
|
-
|
|
1541
|
+
// Allow optional leading whitespace for indented requirements
|
|
1542
|
+
const pyDeps = text.match(/^\s*([a-zA-Z][a-zA-Z0-9_-]*)\s*[=<>~!]/gm) || []
|
|
1225
1543
|
pyDeps.forEach(m => {
|
|
1226
|
-
const match = m.match(
|
|
1544
|
+
const match = m.match(/([a-zA-Z][a-zA-Z0-9_-]*)\s*[=<>~!]/)
|
|
1227
1545
|
if (match) candidates.add(match[1])
|
|
1228
1546
|
})
|
|
1229
1547
|
|
|
1230
1548
|
// Cargo.toml: tokio = "1.0" ā tokio
|
|
1231
|
-
|
|
1549
|
+
// Allow optional leading whitespace for indented dependencies
|
|
1550
|
+
const rustDeps = text.match(/^\s*([a-z][a-z0-9_-]*)\s*=/gm) || []
|
|
1232
1551
|
rustDeps.forEach(m => {
|
|
1233
|
-
const match = m.match(
|
|
1552
|
+
const match = m.match(/([a-z][a-z0-9_-]*)\s*=/)
|
|
1234
1553
|
if (match) candidates.add(match[1])
|
|
1235
1554
|
})
|
|
1236
1555
|
|
|
@@ -1274,10 +1593,14 @@ function extractPotentialLibraryNames(text: string): string[] {
|
|
|
1274
1593
|
if (match) candidates.add(match[1])
|
|
1275
1594
|
})
|
|
1276
1595
|
|
|
1277
|
-
// CamelCase words (FastAPI,
|
|
1596
|
+
// CamelCase words (FastAPI, NextAuth)
|
|
1278
1597
|
const camelCase = text.match(/\b([A-Z][a-z]+(?:[A-Z][a-z]+)+)\b/g) || []
|
|
1279
1598
|
camelCase.forEach(w => candidates.add(w))
|
|
1280
1599
|
|
|
1600
|
+
// Mixed case words (SQLAlchemy, PostgreSQL, GraphQL - uppercase prefix + CamelCase)
|
|
1601
|
+
const mixedCase = text.match(/\b([A-Z]{2,}[a-z]+[A-Za-z]*)\b/g) || []
|
|
1602
|
+
mixedCase.forEach(w => candidates.add(w))
|
|
1603
|
+
|
|
1281
1604
|
// === Pattern 3.5: PascalCase single words after tech keywords ===
|
|
1282
1605
|
// "Framework: Mastra", "ORM: Prisma", "Database: PostgreSQL"
|
|
1283
1606
|
// WHY: Many library names are single PascalCase words (Mastra, Prisma, Django, Flask)
|
|
@@ -1342,34 +1665,35 @@ function extractPotentialLibraryNames(text: string): string[] {
|
|
|
1342
1665
|
})
|
|
1343
1666
|
|
|
1344
1667
|
// === Filter out noise ===
|
|
1668
|
+
// Use lowercase for case-insensitive comparison
|
|
1345
1669
|
const stopWords = new Set([
|
|
1346
|
-
// Common English words
|
|
1347
|
-
'
|
|
1348
|
-
'
|
|
1349
|
-
'
|
|
1350
|
-
'
|
|
1670
|
+
// Common English words (all lowercase for comparison)
|
|
1671
|
+
'the', 'this', 'that', 'with', 'from', 'using', 'for', 'and', 'but', 'not',
|
|
1672
|
+
'all', 'any', 'can', 'could', 'should', 'would', 'will', 'may', 'might',
|
|
1673
|
+
'each', 'every', 'some', 'many', 'most', 'other', 'such', 'only', 'just',
|
|
1674
|
+
'also', 'well', 'back', 'even', 'still', 'already', 'always', 'never',
|
|
1351
1675
|
// Common programming terms that aren't libraries
|
|
1352
|
-
'
|
|
1353
|
-
'
|
|
1354
|
-
'
|
|
1355
|
-
'
|
|
1356
|
-
'
|
|
1357
|
-
'
|
|
1358
|
-
'
|
|
1359
|
-
'
|
|
1360
|
-
'
|
|
1361
|
-
'
|
|
1362
|
-
'
|
|
1363
|
-
'
|
|
1364
|
-
'
|
|
1365
|
-
'
|
|
1676
|
+
'api', 'rest', 'http', 'https', 'json', 'xml', 'html', 'css', 'sql',
|
|
1677
|
+
'get', 'post', 'put', 'delete', 'patch', 'url', 'uri', 'uuid', 'id',
|
|
1678
|
+
'true', 'false', 'none', 'null', 'undefined', 'error', 'exception',
|
|
1679
|
+
'class', 'function', 'method', 'object', 'array', 'string', 'number',
|
|
1680
|
+
'boolean', 'int', 'float', 'double', 'char', 'byte', 'long', 'short',
|
|
1681
|
+
'public', 'private', 'protected', 'static', 'final', 'const', 'let', 'var',
|
|
1682
|
+
'import', 'export', 'module', 'package', 'interface', 'type', 'enum',
|
|
1683
|
+
'test', 'tests', 'spec', 'specs', 'mock', 'stub', 'fake', 'spy',
|
|
1684
|
+
'config', 'configuration', 'settings', 'options', 'params', 'args',
|
|
1685
|
+
'user', 'users', 'admin', 'auth', 'login', 'logout', 'session', 'token',
|
|
1686
|
+
'data', 'database', 'table', 'column', 'row', 'index', 'key', 'value',
|
|
1687
|
+
'file', 'files', 'path', 'dir', 'directory', 'folder', 'name', 'size',
|
|
1688
|
+
'create', 'read', 'update', 'delete', 'list', 'get', 'set', 'add', 'remove',
|
|
1689
|
+
'start', 'stop', 'run', 'build', 'deploy', 'install', 'setup', 'init',
|
|
1366
1690
|
// Version/date patterns
|
|
1367
|
-
'
|
|
1691
|
+
'version', 'release', 'beta', 'alpha', 'stable', 'latest', 'current'
|
|
1368
1692
|
])
|
|
1369
1693
|
|
|
1370
1694
|
return [...candidates]
|
|
1371
1695
|
.filter(w => w.length > 2 && w.length < 30)
|
|
1372
|
-
.filter(w => !stopWords.has(w))
|
|
1696
|
+
.filter(w => !stopWords.has(w.toLowerCase())) // Case-insensitive comparison
|
|
1373
1697
|
.filter(w => !/^\d+$/.test(w)) // Not pure numbers
|
|
1374
1698
|
.filter(w => !/^v?\d+\.\d+/.test(w)) // Not version numbers
|
|
1375
1699
|
.slice(0, 50) // Limit to avoid too many API calls
|
|
@@ -1457,6 +1781,12 @@ function parseContext7Response(response: string, searchTerm: string): {
|
|
|
1457
1781
|
```typescript
|
|
1458
1782
|
output(`\nš Validating Library Capabilities...`)
|
|
1459
1783
|
|
|
1784
|
+
// Initialize variables at function scope
|
|
1785
|
+
let detectedLibraries = []
|
|
1786
|
+
let specRequirements = []
|
|
1787
|
+
let capabilityGaps = []
|
|
1788
|
+
let customImplementationRequired = []
|
|
1789
|
+
|
|
1460
1790
|
// 1. Extract spec requirements from design.md
|
|
1461
1791
|
const designPath = `openspec/changes/${changeId}/design.md`
|
|
1462
1792
|
if (!fileExists(designPath)) {
|
|
@@ -1500,7 +1830,6 @@ if (!fileExists(designPath)) {
|
|
|
1500
1830
|
}
|
|
1501
1831
|
|
|
1502
1832
|
// 3. Detect which libraries are mentioned
|
|
1503
|
-
const detectedLibraries = []
|
|
1504
1833
|
for (const [libName, config] of Object.entries(libraryPatterns)) {
|
|
1505
1834
|
if (config.patterns.some(p => designContent.toLowerCase().includes(p))) {
|
|
1506
1835
|
detectedLibraries.push({ name: libName, ...config })
|
|
@@ -1524,7 +1853,6 @@ if (!fileExists(designPath)) {
|
|
|
1524
1853
|
{ name: 'Account lockout', pattern: /lockout|lock\s*account/i }
|
|
1525
1854
|
]
|
|
1526
1855
|
|
|
1527
|
-
const specRequirements = []
|
|
1528
1856
|
for (const rp of requirementPatterns) {
|
|
1529
1857
|
if (rp.pattern.test(designContent)) {
|
|
1530
1858
|
specRequirements.push(rp.name)
|
|
@@ -1536,8 +1864,6 @@ if (!fileExists(designPath)) {
|
|
|
1536
1864
|
specRequirements.forEach(r => output(` - ${r}`))
|
|
1537
1865
|
|
|
1538
1866
|
// 5. Check each library's capability
|
|
1539
|
-
const capabilityGaps = []
|
|
1540
|
-
|
|
1541
1867
|
for (const lib of detectedLibraries) {
|
|
1542
1868
|
output(`\nš Checking ${lib.name} capabilities...`)
|
|
1543
1869
|
|
|
@@ -1675,12 +2001,12 @@ if (!fileExists(designPath)) {
|
|
|
1675
2001
|
}
|
|
1676
2002
|
}
|
|
1677
2003
|
|
|
1678
|
-
// Store capability analysis
|
|
2004
|
+
// Store capability analysis (variables declared at function scope above)
|
|
1679
2005
|
const capabilityAnalysis = {
|
|
1680
|
-
libraries: detectedLibraries
|
|
1681
|
-
requirements: specRequirements
|
|
1682
|
-
gaps: capabilityGaps
|
|
1683
|
-
customRequired: customImplementationRequired
|
|
2006
|
+
libraries: detectedLibraries,
|
|
2007
|
+
requirements: specRequirements,
|
|
2008
|
+
gaps: capabilityGaps,
|
|
2009
|
+
customRequired: customImplementationRequired
|
|
1684
2010
|
}
|
|
1685
2011
|
```
|
|
1686
2012
|
|
|
@@ -2536,9 +2862,9 @@ if (hasFrontend && tokens) {
|
|
|
2536
2862
|
## šØ Design System (v2.0.0)
|
|
2537
2863
|
|
|
2538
2864
|
**Design Files:**
|
|
2539
|
-
-
|
|
2865
|
+
- data.yaml: \`design-system/data.yaml\` (~800 tokens)
|
|
2540
2866
|
- patterns/: \`design-system/patterns/*.md\` (selective loading)
|
|
2541
|
-
-
|
|
2867
|
+
- README.md: \`design-system/README.md\` (human-readable, ~100 lines)
|
|
2542
2868
|
${pagePlan ? `- page-plan.md: \`openspec/changes/${changeId}/page-plan.md\` ā
` : ''}
|
|
2543
2869
|
|
|
2544
2870
|
**Style Direction:**
|
|
@@ -2577,7 +2903,7 @@ pageType.includes('auth') ?
|
|
|
2577
2903
|
- patterns/forms.md ā
`}
|
|
2578
2904
|
|
|
2579
2905
|
**Agent Loading (STEP 0.5 for uxui-frontend):**
|
|
2580
|
-
1. Read:
|
|
2906
|
+
1. Read: data.yaml (~800 tokens)
|
|
2581
2907
|
2. Read: page-plan.md (if exists)
|
|
2582
2908
|
3. Load patterns selectively based on page type
|
|
2583
2909
|
4. Report: Design tokens + page type extracted
|