@ryuenn3123/agentic-senior-core 2.5.18 → 2.5.20
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/.agent-context/state/memory-continuity-benchmark.json +1 -1
- package/.agent-context/state/stack-research-snapshot.json +112 -0
- package/.cursorrules +1 -1
- package/.windsurfrules +1 -1
- package/README.md +12 -0
- package/lib/cli/architect.mjs +656 -5
- package/lib/cli/commands/init.mjs +198 -9
- package/lib/cli/commands/upgrade.mjs +64 -1
- package/lib/cli/compiler.mjs +2 -0
- package/lib/cli/utils.mjs +4 -1
- package/package.json +1 -1
- package/scripts/validate.mjs +161 -0
|
@@ -65,6 +65,7 @@ import { evaluateSkillDomainCompatibility } from '../compatibility.mjs';
|
|
|
65
65
|
import {
|
|
66
66
|
ARCHITECT_DEFAULT_TOKEN_BUDGET,
|
|
67
67
|
ARCHITECT_DEFAULT_TIMEOUT_MS,
|
|
68
|
+
ARCHITECT_DEFAULT_RESEARCH_MODE,
|
|
68
69
|
ARCHITECT_MIN_TOKEN_BUDGET,
|
|
69
70
|
ARCHITECT_MAX_TOKEN_BUDGET,
|
|
70
71
|
ARCHITECT_MIN_TIMEOUT_MS,
|
|
@@ -100,6 +101,9 @@ export function parseInitArguments(commandArguments) {
|
|
|
100
101
|
projectDescription: '',
|
|
101
102
|
architectTokenBudget: ARCHITECT_DEFAULT_TOKEN_BUDGET,
|
|
102
103
|
architectTimeoutMs: ARCHITECT_DEFAULT_TIMEOUT_MS,
|
|
104
|
+
architectResearchMode: ARCHITECT_DEFAULT_RESEARCH_MODE,
|
|
105
|
+
enableRealtimeResearch: false,
|
|
106
|
+
architectRealtimeSignalFile: null,
|
|
103
107
|
runtimeEnv: 'auto',
|
|
104
108
|
runtimeEnvProvided: false,
|
|
105
109
|
};
|
|
@@ -308,6 +312,38 @@ export function parseInitArguments(commandArguments) {
|
|
|
308
312
|
continue;
|
|
309
313
|
}
|
|
310
314
|
|
|
315
|
+
if (currentArgument === '--architect-research-mode') {
|
|
316
|
+
parsedInitOptions.architectResearchMode = commandArguments[argumentIndex + 1] || ARCHITECT_DEFAULT_RESEARCH_MODE;
|
|
317
|
+
argumentIndex += 1;
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
if (currentArgument.startsWith('--architect-research-mode=')) {
|
|
322
|
+
parsedInitOptions.architectResearchMode = currentArgument.split('=')[1] || ARCHITECT_DEFAULT_RESEARCH_MODE;
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if (currentArgument === '--enable-realtime-research') {
|
|
327
|
+
parsedInitOptions.enableRealtimeResearch = true;
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (currentArgument === '--disable-realtime-research') {
|
|
332
|
+
parsedInitOptions.enableRealtimeResearch = false;
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
if (currentArgument === '--architect-realtime-signal-file') {
|
|
337
|
+
parsedInitOptions.architectRealtimeSignalFile = commandArguments[argumentIndex + 1] || null;
|
|
338
|
+
argumentIndex += 1;
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (currentArgument.startsWith('--architect-realtime-signal-file=')) {
|
|
343
|
+
parsedInitOptions.architectRealtimeSignalFile = currentArgument.split('=')[1] || null;
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
|
|
311
347
|
if (currentArgument === '--runtime-env') {
|
|
312
348
|
parsedInitOptions.runtimeEnv = commandArguments[argumentIndex + 1] || 'auto';
|
|
313
349
|
parsedInitOptions.runtimeEnvProvided = true;
|
|
@@ -350,9 +386,18 @@ export function parseInitArguments(commandArguments) {
|
|
|
350
386
|
throw new Error(`--architect-timeout-ms must be an integer between ${ARCHITECT_MIN_TIMEOUT_MS} and ${ARCHITECT_MAX_TIMEOUT_MS}`);
|
|
351
387
|
}
|
|
352
388
|
|
|
389
|
+
const normalizedArchitectResearchMode = normalizeChoiceInput(
|
|
390
|
+
parsedInitOptions.architectResearchMode || ARCHITECT_DEFAULT_RESEARCH_MODE
|
|
391
|
+
);
|
|
392
|
+
const supportedArchitectResearchModes = new Set(['snapshot', 'realtime']);
|
|
393
|
+
if (!supportedArchitectResearchModes.has(normalizedArchitectResearchMode)) {
|
|
394
|
+
throw new Error('--architect-research-mode must be one of: snapshot, realtime');
|
|
395
|
+
}
|
|
396
|
+
|
|
353
397
|
parsedInitOptions.docsLang = normalizedDocsLanguage;
|
|
354
398
|
parsedInitOptions.runtimeEnv = normalizedRuntimeEnvironment;
|
|
355
399
|
parsedInitOptions.tokenAgent = normalizeAgentName(parsedInitOptions.tokenAgent);
|
|
400
|
+
parsedInitOptions.architectResearchMode = normalizedArchitectResearchMode;
|
|
356
401
|
|
|
357
402
|
return parsedInitOptions;
|
|
358
403
|
}
|
|
@@ -502,6 +547,14 @@ async function askBlueprintSelection(promptMessage, selectableBlueprintFileNames
|
|
|
502
547
|
return selectableBlueprintFileNames[selectedIndex] || selectableBlueprintFileNames[0] || null;
|
|
503
548
|
}
|
|
504
549
|
|
|
550
|
+
function buildExistingProjectMajorConstraints() {
|
|
551
|
+
return [
|
|
552
|
+
'Preserve existing project markers and avoid forced stack migration.',
|
|
553
|
+
'Keep stack rule loading lazy and scoped to touched code.',
|
|
554
|
+
'Explicit stack or blueprint overrides always win over auto-detection.',
|
|
555
|
+
];
|
|
556
|
+
}
|
|
557
|
+
|
|
505
558
|
export async function runInitCommand(targetDirectoryArgument, initOptions = {}) {
|
|
506
559
|
const resolvedTargetDirectoryPath = path.resolve(targetDirectoryArgument || '.');
|
|
507
560
|
const isTokenOptimizationEnabled = typeof initOptions.tokenOptimize === 'boolean'
|
|
@@ -654,6 +707,64 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
654
707
|
console.log(`\nSelected profile: ${selectedProfile.displayName}`);
|
|
655
708
|
console.log(`This profile will block these review severities in CI: ${formatBlockingSeverities(selectedProfile.blockingSeverities)}.`);
|
|
656
709
|
|
|
710
|
+
const detectionMajorConstraints = buildExistingProjectMajorConstraints();
|
|
711
|
+
const detectionTransparency = {
|
|
712
|
+
declaredAt: new Date().toISOString(),
|
|
713
|
+
declarationType: projectDetection.hasExistingProjectFiles ? 'existing-project' : 'fresh-project',
|
|
714
|
+
declarationShown: projectDetection.hasExistingProjectFiles,
|
|
715
|
+
detectionSummary: projectDetection.hasExistingProjectFiles
|
|
716
|
+
? buildDetectionSummary(projectDetection)
|
|
717
|
+
: 'No existing project markers were detected.',
|
|
718
|
+
activeRulesSummary: {
|
|
719
|
+
canonicalSource: '.instructions.md',
|
|
720
|
+
compiledEntrypoints: ['.cursorrules', '.windsurfrules'],
|
|
721
|
+
stackLoadingMode: 'lazy',
|
|
722
|
+
selectedProfile: selectedProfileName,
|
|
723
|
+
selectedProfileDisplayName: selectedProfile.displayName,
|
|
724
|
+
blockingSeverities: selectedProfile.blockingSeverities,
|
|
725
|
+
ciGuardrailsEnabled: null,
|
|
726
|
+
},
|
|
727
|
+
majorConstraints: detectionMajorConstraints,
|
|
728
|
+
quickConfirmation: {
|
|
729
|
+
offered: false,
|
|
730
|
+
response: projectDetection.hasExistingProjectFiles ? 'pending' : 'not-applicable',
|
|
731
|
+
source: 'existing-project-detection',
|
|
732
|
+
},
|
|
733
|
+
decision: {
|
|
734
|
+
mode: projectDetection.hasExistingProjectFiles ? 'pending' : 'fresh-directory',
|
|
735
|
+
selectedStackFileName: null,
|
|
736
|
+
selectedBlueprintFileName: null,
|
|
737
|
+
},
|
|
738
|
+
};
|
|
739
|
+
|
|
740
|
+
if (projectDetection.hasExistingProjectFiles) {
|
|
741
|
+
console.log('\nExisting project detection transparency:');
|
|
742
|
+
|
|
743
|
+
if (projectDetection.recommendedStackFileName) {
|
|
744
|
+
const confidenceScoreLabel = Number(projectDetection.confidenceScore || 0).toFixed(2);
|
|
745
|
+
console.log(
|
|
746
|
+
`- Detected stack: ${toTitleCase(projectDetection.recommendedStackFileName)} (${projectDetection.confidenceLabel}, score ${confidenceScoreLabel})`
|
|
747
|
+
);
|
|
748
|
+
|
|
749
|
+
if (projectDetection.secondaryStackFileNames?.length) {
|
|
750
|
+
console.log(
|
|
751
|
+
`- Secondary stack signals: ${projectDetection.secondaryStackFileNames.map((stackFileName) => toTitleCase(stackFileName)).join(', ')}`
|
|
752
|
+
);
|
|
753
|
+
}
|
|
754
|
+
} else {
|
|
755
|
+
console.log('- Detected stack: unresolved (insufficient markers).');
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
console.log('- Active rules baseline: canonical .instructions.md -> compiled .cursorrules/.windsurfrules');
|
|
759
|
+
console.log(
|
|
760
|
+
`- Active review profile: ${selectedProfile.displayName} (blocking severities: ${formatBlockingSeverities(selectedProfile.blockingSeverities)})`
|
|
761
|
+
);
|
|
762
|
+
console.log('- Major constraints:');
|
|
763
|
+
for (const majorConstraint of detectionMajorConstraints) {
|
|
764
|
+
console.log(` - ${majorConstraint}`);
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
|
|
657
768
|
if (selectedProfilePack) {
|
|
658
769
|
console.log(`Applying team profile pack: ${selectedProfilePack.displayName}.`);
|
|
659
770
|
console.log(`Pack defaults: stack ${toTitleCase(selectedProfilePack.defaultStackFileName)}, blueprint ${toTitleCase(selectedProfilePack.defaultBlueprintFileName)}.`);
|
|
@@ -667,11 +778,15 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
667
778
|
&& !selectedStackFileNameFromOption
|
|
668
779
|
&& !selectedPreset?.stack
|
|
669
780
|
&& !selectedProfilePack?.defaultStackFileName;
|
|
781
|
+
const detectedBlueprintFileName = projectDetection.recommendedBlueprintFileName
|
|
782
|
+
|| BLUEPRINT_RECOMMENDATIONS[projectDetection.recommendedStackFileName]
|
|
783
|
+
|| null;
|
|
670
784
|
|
|
671
785
|
let selectedManualStackFileName = null;
|
|
672
786
|
let selectedManualBlueprintFileName = null;
|
|
673
787
|
let selectedAdditionalStackFileNames = [];
|
|
674
788
|
let selectedAdditionalBlueprintFileNames = [];
|
|
789
|
+
let detectedSetupWasApplied = false;
|
|
675
790
|
|
|
676
791
|
let architectureRecommendation = null;
|
|
677
792
|
let architectPreferenceState = await readArchitectPreferenceState();
|
|
@@ -684,11 +799,73 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
684
799
|
&& !selectedProfile.defaultStackFileName;
|
|
685
800
|
|
|
686
801
|
if (shouldAutoApplyDetectedStack) {
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
console.log(
|
|
802
|
+
if (isInteractiveSession) {
|
|
803
|
+
detectionTransparency.quickConfirmation.offered = true;
|
|
804
|
+
console.log('\nQuick confirmation for existing project detection:');
|
|
805
|
+
console.log(`- Suggested stack: ${toTitleCase(projectDetection.recommendedStackFileName)}`);
|
|
806
|
+
if (detectedBlueprintFileName) {
|
|
807
|
+
console.log(`- Suggested blueprint: ${toTitleCase(detectedBlueprintFileName)}`);
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
const shouldUseDetectedSetup = await askYesNo(
|
|
811
|
+
'Use detected setup for this existing project?',
|
|
812
|
+
userInterface,
|
|
813
|
+
true
|
|
814
|
+
);
|
|
815
|
+
|
|
816
|
+
if (shouldUseDetectedSetup) {
|
|
817
|
+
detectedSetupWasApplied = true;
|
|
818
|
+
detectionTransparency.quickConfirmation.response = 'confirmed-detected';
|
|
819
|
+
detectionTransparency.decision.mode = 'confirmed-detected';
|
|
820
|
+
console.log(`Using detected stack automatically for this existing project: ${toTitleCase(projectDetection.recommendedStackFileName)}.`);
|
|
821
|
+
if (projectDetection.secondaryStackFileNames?.length) {
|
|
822
|
+
console.log(`Detected additional stack signals: ${projectDetection.secondaryStackFileNames.map((stackFileName) => toTitleCase(stackFileName)).join(', ')}.`);
|
|
823
|
+
}
|
|
824
|
+
selectedAdditionalStackFileNames = projectDetection.secondaryStackFileNames || [];
|
|
825
|
+
} else {
|
|
826
|
+
const overrideStackFileName = await askStackSelection(
|
|
827
|
+
'Override detected stack (quick selection):',
|
|
828
|
+
stackFileNames,
|
|
829
|
+
userInterface
|
|
830
|
+
);
|
|
831
|
+
const overrideBlueprintCandidates = filterBlueprintFileNamesByCandidates(
|
|
832
|
+
blueprintFileNames,
|
|
833
|
+
[BLUEPRINT_RECOMMENDATIONS[overrideStackFileName]].filter(Boolean)
|
|
834
|
+
);
|
|
835
|
+
const overrideBlueprintFileName = await askBlueprintSelection(
|
|
836
|
+
'Override detected blueprint (quick selection):',
|
|
837
|
+
overrideBlueprintCandidates,
|
|
838
|
+
userInterface
|
|
839
|
+
);
|
|
840
|
+
|
|
841
|
+
selectedManualStackFileName = overrideStackFileName;
|
|
842
|
+
selectedManualBlueprintFileName = overrideBlueprintFileName;
|
|
843
|
+
selectedAdditionalStackFileNames = normalizeAdditionalStackSelection(
|
|
844
|
+
overrideStackFileName,
|
|
845
|
+
projectDetection.secondaryStackFileNames || []
|
|
846
|
+
);
|
|
847
|
+
detectionTransparency.quickConfirmation.response = 'overridden-detected';
|
|
848
|
+
detectionTransparency.decision.mode = 'overridden-detected';
|
|
849
|
+
console.log(
|
|
850
|
+
`Detection override applied: ${toTitleCase(overrideStackFileName)} + ${toTitleCase(overrideBlueprintFileName)}.`
|
|
851
|
+
);
|
|
852
|
+
}
|
|
853
|
+
} else {
|
|
854
|
+
detectedSetupWasApplied = true;
|
|
855
|
+
detectionTransparency.quickConfirmation.response = 'non-interactive-auto';
|
|
856
|
+
detectionTransparency.decision.mode = 'non-interactive-auto';
|
|
857
|
+
console.log(`Using detected stack automatically for this existing project: ${toTitleCase(projectDetection.recommendedStackFileName)}.`);
|
|
858
|
+
if (projectDetection.secondaryStackFileNames?.length) {
|
|
859
|
+
console.log(`Detected additional stack signals: ${projectDetection.secondaryStackFileNames.map((stackFileName) => toTitleCase(stackFileName)).join(', ')}.`);
|
|
860
|
+
}
|
|
861
|
+
selectedAdditionalStackFileNames = projectDetection.secondaryStackFileNames || [];
|
|
690
862
|
}
|
|
691
|
-
|
|
863
|
+
} else if (projectDetection.hasExistingProjectFiles && projectDetection.recommendedStackFileName) {
|
|
864
|
+
detectionTransparency.quickConfirmation.response = 'explicit-selection-or-low-confidence';
|
|
865
|
+
detectionTransparency.decision.mode = 'explicit-selection-or-low-confidence';
|
|
866
|
+
} else if (!projectDetection.hasExistingProjectFiles) {
|
|
867
|
+
detectionTransparency.quickConfirmation.response = 'not-applicable';
|
|
868
|
+
detectionTransparency.decision.mode = 'fresh-directory';
|
|
692
869
|
}
|
|
693
870
|
|
|
694
871
|
if (shouldRunArchitectureRecommendation) {
|
|
@@ -711,6 +888,9 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
711
888
|
blueprintFileNames,
|
|
712
889
|
tokenBudget: initOptions.architectTokenBudget,
|
|
713
890
|
timeoutMs: initOptions.architectTimeoutMs,
|
|
891
|
+
researchMode: initOptions.architectResearchMode,
|
|
892
|
+
enableRealtimeResearch: initOptions.enableRealtimeResearch,
|
|
893
|
+
realtimeSignalFilePath: initOptions.architectRealtimeSignalFile,
|
|
714
894
|
});
|
|
715
895
|
|
|
716
896
|
architectureRecommendation.userVeto = {
|
|
@@ -805,10 +985,10 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
805
985
|
|
|
806
986
|
const selectedResolvedStackFileName = selectedStackFileNameFromOption
|
|
807
987
|
|| selectedPreset?.stack
|
|
808
|
-
||
|
|
988
|
+
|| selectedManualStackFileName
|
|
989
|
+
|| (detectedSetupWasApplied ? projectDetection.recommendedStackFileName : null)
|
|
809
990
|
|| selectedProfilePack?.defaultStackFileName
|
|
810
991
|
|| selectedProfile.defaultStackFileName
|
|
811
|
-
|| selectedManualStackFileName
|
|
812
992
|
|| stackFileNames[0];
|
|
813
993
|
|
|
814
994
|
selectedAdditionalStackFileNames = normalizeAdditionalStackSelection(
|
|
@@ -816,9 +996,9 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
816
996
|
selectedAdditionalStackFileNames
|
|
817
997
|
);
|
|
818
998
|
|
|
819
|
-
const recommendedBlueprintFileName =
|
|
820
|
-
&&
|
|
821
|
-
?
|
|
999
|
+
const recommendedBlueprintFileName = detectedSetupWasApplied
|
|
1000
|
+
&& detectedBlueprintFileName
|
|
1001
|
+
? detectedBlueprintFileName
|
|
822
1002
|
: BLUEPRINT_RECOMMENDATIONS[selectedResolvedStackFileName] || null;
|
|
823
1003
|
|
|
824
1004
|
if (!recommendedBlueprintFileName && !selectedBlueprintFileNameFromOption && !selectedProfile.defaultBlueprintFileName) {
|
|
@@ -864,6 +1044,12 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
864
1044
|
: derivedAdditionalBlueprintFileNames
|
|
865
1045
|
);
|
|
866
1046
|
|
|
1047
|
+
detectionTransparency.decision.selectedStackFileName = selectedResolvedStackFileName;
|
|
1048
|
+
detectionTransparency.decision.selectedBlueprintFileName = selectedResolvedBlueprintFileName;
|
|
1049
|
+
detectionTransparency.decision.selectedAdditionalStackFileNames = selectedAdditionalStackFileNames;
|
|
1050
|
+
detectionTransparency.decision.selectedAdditionalBlueprintFileNames = selectedAdditionalBlueprintFileNames;
|
|
1051
|
+
detectionTransparency.decision.usedDetectedSetup = detectedSetupWasApplied;
|
|
1052
|
+
|
|
867
1053
|
const selectedSkillDomainNames = inferSkillDomainNamesFromSelection(
|
|
868
1054
|
selectedResolvedStackFileName,
|
|
869
1055
|
selectedResolvedBlueprintFileName,
|
|
@@ -883,6 +1069,8 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
883
1069
|
? selectedProfile.defaultCi
|
|
884
1070
|
: await askYesNo('Enable CI/CD quality checks (guardrails) and the LLM Judge policy?', userInterface, selectedProfile.defaultCi);
|
|
885
1071
|
|
|
1072
|
+
detectionTransparency.activeRulesSummary.ciGuardrailsEnabled = includeCiGuardrails;
|
|
1073
|
+
|
|
886
1074
|
await copyGovernanceAssetsToTarget(resolvedTargetDirectoryPath, {
|
|
887
1075
|
includeMcpTemplate: shouldIncludeMcpTemplate,
|
|
888
1076
|
});
|
|
@@ -1044,6 +1232,7 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
1044
1232
|
stateFile: isMemoryContinuityEnabled ? '.agent-context/state/memory-continuity.json' : null,
|
|
1045
1233
|
},
|
|
1046
1234
|
architectRecommendation: architectureRecommendation,
|
|
1235
|
+
detectionTransparency,
|
|
1047
1236
|
});
|
|
1048
1237
|
|
|
1049
1238
|
if (architectPreferenceUpdated && architectPreferenceState) {
|
|
@@ -24,7 +24,11 @@ import {
|
|
|
24
24
|
copyGovernanceAssetsToTarget,
|
|
25
25
|
} from '../utils.mjs';
|
|
26
26
|
|
|
27
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
detectProjectContext,
|
|
29
|
+
buildDetectionSummary,
|
|
30
|
+
formatDetectionCandidates,
|
|
31
|
+
} from '../detector.mjs';
|
|
28
32
|
import {
|
|
29
33
|
buildCompiledRulesContent,
|
|
30
34
|
writeSelectedPolicy,
|
|
@@ -76,6 +80,14 @@ export function parseUpgradeArguments(commandArguments) {
|
|
|
76
80
|
return parsedUpgradeOptions;
|
|
77
81
|
}
|
|
78
82
|
|
|
83
|
+
function buildExistingProjectMajorConstraints() {
|
|
84
|
+
return [
|
|
85
|
+
'Preserve existing project markers and avoid forced stack migration.',
|
|
86
|
+
'Keep stack rule loading lazy and scoped to touched code.',
|
|
87
|
+
'Upgrade keeps prior onboarding choices unless user overrides them.',
|
|
88
|
+
];
|
|
89
|
+
}
|
|
90
|
+
|
|
79
91
|
export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions = {}) {
|
|
80
92
|
const resolvedTargetDirectoryPath = path.resolve(targetDirectoryArgument || '.');
|
|
81
93
|
|
|
@@ -143,6 +155,56 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
|
|
|
143
155
|
? existingOnboardingReport.ciGuardrailsEnabled
|
|
144
156
|
: true;
|
|
145
157
|
|
|
158
|
+
const detectionMajorConstraints = buildExistingProjectMajorConstraints();
|
|
159
|
+
const detectionTransparency = {
|
|
160
|
+
declaredAt: new Date().toISOString(),
|
|
161
|
+
declarationType: 'existing-project',
|
|
162
|
+
declarationShown: true,
|
|
163
|
+
detectionSummary: buildDetectionSummary(projectDetection),
|
|
164
|
+
activeRulesSummary: {
|
|
165
|
+
canonicalSource: '.instructions.md',
|
|
166
|
+
compiledEntrypoints: ['.cursorrules', '.windsurfrules'],
|
|
167
|
+
stackLoadingMode: 'lazy',
|
|
168
|
+
selectedProfile: selectedProfileName,
|
|
169
|
+
selectedProfileDisplayName: toTitleCase(selectedProfileName),
|
|
170
|
+
blockingSeverities: PROFILE_PRESETS[selectedProfileName]?.blockingSeverities || [],
|
|
171
|
+
ciGuardrailsEnabled: includeCiGuardrails,
|
|
172
|
+
},
|
|
173
|
+
majorConstraints: detectionMajorConstraints,
|
|
174
|
+
quickConfirmation: {
|
|
175
|
+
offered: false,
|
|
176
|
+
response: 'upgrade-auto',
|
|
177
|
+
source: 'upgrade-assistant',
|
|
178
|
+
},
|
|
179
|
+
decision: {
|
|
180
|
+
mode: 'upgrade-auto',
|
|
181
|
+
selectedStackFileName,
|
|
182
|
+
selectedBlueprintFileName,
|
|
183
|
+
},
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
console.log('\nExisting project detection transparency:');
|
|
187
|
+
if (projectDetection.recommendedStackFileName) {
|
|
188
|
+
const confidenceScoreLabel = Number(projectDetection.confidenceScore || 0).toFixed(2);
|
|
189
|
+
console.log(
|
|
190
|
+
`- Detected stack: ${toTitleCase(projectDetection.recommendedStackFileName)} (${projectDetection.confidenceLabel}, score ${confidenceScoreLabel})`
|
|
191
|
+
);
|
|
192
|
+
} else {
|
|
193
|
+
console.log('- Detected stack: unresolved (insufficient markers).');
|
|
194
|
+
}
|
|
195
|
+
console.log('- Active rules baseline: canonical .instructions.md -> compiled .cursorrules/.windsurfrules');
|
|
196
|
+
console.log(
|
|
197
|
+
`- Active review profile: ${toTitleCase(selectedProfileName)} (blocking severities: ${(
|
|
198
|
+
PROFILE_PRESETS[selectedProfileName]?.blockingSeverities || []
|
|
199
|
+
).join(', ') || 'none'})`
|
|
200
|
+
);
|
|
201
|
+
console.log('- Top candidates:');
|
|
202
|
+
console.log(formatDetectionCandidates(projectDetection.rankedCandidates));
|
|
203
|
+
console.log('- Major constraints:');
|
|
204
|
+
for (const majorConstraint of detectionMajorConstraints) {
|
|
205
|
+
console.log(` - ${majorConstraint}`);
|
|
206
|
+
}
|
|
207
|
+
|
|
146
208
|
const selectedSkillDomainNames = inferSkillDomainNamesFromSelection(
|
|
147
209
|
selectedStackFileName,
|
|
148
210
|
selectedBlueprintFileName,
|
|
@@ -249,6 +311,7 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
|
|
|
249
311
|
compatibilityWarnings,
|
|
250
312
|
runtimeEnvironment: existingOnboardingReport?.runtimeEnvironment || null,
|
|
251
313
|
operationMode: 'upgrade',
|
|
314
|
+
detectionTransparency,
|
|
252
315
|
});
|
|
253
316
|
|
|
254
317
|
console.log('\nUpgrade complete.');
|
package/lib/cli/compiler.mjs
CHANGED
|
@@ -56,6 +56,7 @@ export async function writeOnboardingReport({
|
|
|
56
56
|
tokenOptimization = undefined,
|
|
57
57
|
memoryContinuity = undefined,
|
|
58
58
|
architectRecommendation = null,
|
|
59
|
+
detectionTransparency = null,
|
|
59
60
|
}) {
|
|
60
61
|
const onboardingReportPath = path.join(targetDirectoryPath, '.agent-context', 'state', 'onboarding-report.json');
|
|
61
62
|
const resolvedTokenOptimization = typeof tokenOptimization === 'undefined'
|
|
@@ -110,6 +111,7 @@ export async function writeOnboardingReport({
|
|
|
110
111
|
detectionReasoning: projectDetection.detectionReasoning,
|
|
111
112
|
rankedCandidates: projectDetection.rankedCandidates,
|
|
112
113
|
evidence: projectDetection.evidence,
|
|
114
|
+
detectionTransparency: detectionTransparency || null,
|
|
113
115
|
},
|
|
114
116
|
};
|
|
115
117
|
|
package/lib/cli/utils.mjs
CHANGED
|
@@ -29,7 +29,7 @@ export function printUsage() {
|
|
|
29
29
|
console.log('');
|
|
30
30
|
console.log('Usage:');
|
|
31
31
|
console.log(' agentic-senior-core launch');
|
|
32
|
-
console.log(' agentic-senior-core init [target-directory] [--preset <name>] [--profile <beginner|balanced|strict>] [--profile-pack <name>] [--stack <name>] [--blueprint <name>] [--project-description <text>] [--architect-token-budget <number>] [--architect-timeout-ms <number>] [--ci <true|false>] [--newbie] [--token-optimize] [--no-token-optimize] [--token-agent <name>] [--memory-continuity] [--no-memory-continuity] [--scaffold-docs] [--no-scaffold-docs] [--docs-lang <en|id>] [--project-config <path>] [--runtime-env <auto|linux-wsl|linux|windows|macos>]');
|
|
32
|
+
console.log(' agentic-senior-core init [target-directory] [--preset <name>] [--profile <beginner|balanced|strict>] [--profile-pack <name>] [--stack <name>] [--blueprint <name>] [--project-description <text>] [--architect-token-budget <number>] [--architect-timeout-ms <number>] [--architect-research-mode <snapshot|realtime>] [--enable-realtime-research] [--architect-realtime-signal-file <path>] [--ci <true|false>] [--newbie] [--token-optimize] [--no-token-optimize] [--token-agent <name>] [--memory-continuity] [--no-memory-continuity] [--scaffold-docs] [--no-scaffold-docs] [--docs-lang <en|id>] [--project-config <path>] [--runtime-env <auto|linux-wsl|linux|windows|macos>]');
|
|
33
33
|
console.log(' agentic-senior-core upgrade [target-directory] [--dry-run] [--yes] [--mcp-template]');
|
|
34
34
|
console.log(' agentic-senior-core optimize [target-directory] [--agent <copilot|claude|cursor|windsurf|gemini|codex|cline>] [--enable|--disable] [--show]');
|
|
35
35
|
console.log(' agentic-senior-core mcp');
|
|
@@ -49,6 +49,9 @@ export function printUsage() {
|
|
|
49
49
|
console.log(' --project-description Architecture intent text used for stack/blueprint recommendation');
|
|
50
50
|
console.log(' --architect-token-budget Max token estimate used by recommendation research (default: 900)');
|
|
51
51
|
console.log(' --architect-timeout-ms Max recommendation research time in milliseconds (default: 1500)');
|
|
52
|
+
console.log(' --architect-research-mode Recommendation evidence mode (snapshot or realtime; default: snapshot)');
|
|
53
|
+
console.log(' --enable-realtime-research Explicit gate to allow trusted realtime evidence ingestion');
|
|
54
|
+
console.log(' --architect-realtime-signal-file Optional JSON payload path for trusted realtime stack/design signals');
|
|
52
55
|
console.log(' --ci Override CI/CD quality checks (guardrails) (true|false)');
|
|
53
56
|
console.log(' --token-optimize Explicitly enable token optimization policy during init (default behavior)');
|
|
54
57
|
console.log(' --token-agent Set token optimization agent target (copilot, claude, cursor, windsurf, gemini, codex, cline)');
|
package/package.json
CHANGED
package/scripts/validate.mjs
CHANGED
|
@@ -155,6 +155,54 @@ const REQUIRED_COMPLIANCE_CANONICAL_SNIPPETS = [
|
|
|
155
155
|
label: 'release operations checklist keeps canonical term Federated Governance',
|
|
156
156
|
},
|
|
157
157
|
];
|
|
158
|
+
const REQUIRED_DETECTION_TRANSPARENCY_SNIPPETS = [
|
|
159
|
+
{
|
|
160
|
+
path: 'lib/cli/commands/init.mjs',
|
|
161
|
+
snippets: [
|
|
162
|
+
'Existing project detection transparency:',
|
|
163
|
+
'Use detected setup for this existing project?',
|
|
164
|
+
'detectionTransparency',
|
|
165
|
+
],
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
path: 'lib/cli/commands/upgrade.mjs',
|
|
169
|
+
snippets: [
|
|
170
|
+
'Existing project detection transparency:',
|
|
171
|
+
'formatDetectionCandidates(projectDetection.rankedCandidates)',
|
|
172
|
+
'detectionTransparency',
|
|
173
|
+
],
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
path: 'lib/cli/compiler.mjs',
|
|
177
|
+
snippets: [
|
|
178
|
+
'detectionTransparency = null',
|
|
179
|
+
'detectionTransparency: detectionTransparency || null',
|
|
180
|
+
],
|
|
181
|
+
},
|
|
182
|
+
];
|
|
183
|
+
const REQUIRED_STACK_RESEARCH_ENGINE_SNIPPETS = [
|
|
184
|
+
{
|
|
185
|
+
path: 'lib/cli/architect.mjs',
|
|
186
|
+
snippets: [
|
|
187
|
+
'ARCHITECT_RESEARCH_SNAPSHOT_FILE_PATH',
|
|
188
|
+
'evidenceCitations',
|
|
189
|
+
'designGuidance',
|
|
190
|
+
'copiedExternalProse: false',
|
|
191
|
+
'realtimeGateEnabled',
|
|
192
|
+
'requestedMode: requestedResearchMode',
|
|
193
|
+
],
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
path: 'lib/cli/commands/init.mjs',
|
|
197
|
+
snippets: [
|
|
198
|
+
'--architect-research-mode',
|
|
199
|
+
'--enable-realtime-research',
|
|
200
|
+
'--architect-realtime-signal-file',
|
|
201
|
+
'researchMode: initOptions.architectResearchMode',
|
|
202
|
+
'enableRealtimeResearch: initOptions.enableRealtimeResearch',
|
|
203
|
+
],
|
|
204
|
+
},
|
|
205
|
+
];
|
|
158
206
|
|
|
159
207
|
const validationResult = {
|
|
160
208
|
passed: 0,
|
|
@@ -275,6 +323,7 @@ async function validateRequiredFiles() {
|
|
|
275
323
|
'.agent-context/state/benchmark-reproducibility.json',
|
|
276
324
|
'.agent-context/state/benchmark-writer-judge-config.json',
|
|
277
325
|
'.agent-context/state/benchmark-watchlist.json',
|
|
326
|
+
'.agent-context/state/stack-research-snapshot.json',
|
|
278
327
|
'.agent-context/state/memory-schema-v1.json',
|
|
279
328
|
'.agent-context/state/memory-adapter-contract.json',
|
|
280
329
|
'.agent-context/state/skill-platform.json',
|
|
@@ -928,6 +977,115 @@ async function validateTerminologyMapping() {
|
|
|
928
977
|
}
|
|
929
978
|
}
|
|
930
979
|
|
|
980
|
+
async function validateDetectionTransparencyCoverage() {
|
|
981
|
+
console.log('\nChecking existing-project detection transparency coverage...');
|
|
982
|
+
|
|
983
|
+
for (const transparencyRule of REQUIRED_DETECTION_TRANSPARENCY_SNIPPETS) {
|
|
984
|
+
const absoluteTransparencyPath = join(ROOT_DIR, transparencyRule.path);
|
|
985
|
+
|
|
986
|
+
if (!(await fileExists(absoluteTransparencyPath))) {
|
|
987
|
+
fail(`Missing detection transparency source: ${transparencyRule.path}`);
|
|
988
|
+
continue;
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
const transparencyContent = await readTextFile(absoluteTransparencyPath);
|
|
992
|
+
for (const requiredSnippet of transparencyRule.snippets) {
|
|
993
|
+
if (transparencyContent.includes(requiredSnippet)) {
|
|
994
|
+
pass(`${transparencyRule.path} includes detection transparency snippet: ${requiredSnippet}`);
|
|
995
|
+
} else {
|
|
996
|
+
fail(`${transparencyRule.path} is missing detection transparency snippet: ${requiredSnippet}`);
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
async function validateStackResearchEngineCoverage() {
|
|
1003
|
+
console.log('\nChecking stack research engine coverage...');
|
|
1004
|
+
|
|
1005
|
+
for (const coverageRule of REQUIRED_STACK_RESEARCH_ENGINE_SNIPPETS) {
|
|
1006
|
+
const absoluteCoveragePath = join(ROOT_DIR, coverageRule.path);
|
|
1007
|
+
|
|
1008
|
+
if (!(await fileExists(absoluteCoveragePath))) {
|
|
1009
|
+
fail(`Missing stack research source: ${coverageRule.path}`);
|
|
1010
|
+
continue;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
const coverageContent = await readTextFile(absoluteCoveragePath);
|
|
1014
|
+
for (const requiredSnippet of coverageRule.snippets) {
|
|
1015
|
+
if (coverageContent.includes(requiredSnippet)) {
|
|
1016
|
+
pass(`${coverageRule.path} includes stack research snippet: ${requiredSnippet}`);
|
|
1017
|
+
} else {
|
|
1018
|
+
fail(`${coverageRule.path} is missing stack research snippet: ${requiredSnippet}`);
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
function isNormalizedMetricValue(value) {
|
|
1025
|
+
return Number.isFinite(Number(value)) && Number(value) >= 0 && Number(value) <= 1;
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
async function validateStackResearchSnapshotState() {
|
|
1029
|
+
console.log('\nChecking deterministic stack research snapshot state...');
|
|
1030
|
+
|
|
1031
|
+
const snapshotPath = join(ROOT_DIR, '.agent-context', 'state', 'stack-research-snapshot.json');
|
|
1032
|
+
if (!(await fileExists(snapshotPath))) {
|
|
1033
|
+
fail('Missing deterministic stack research snapshot: .agent-context/state/stack-research-snapshot.json');
|
|
1034
|
+
return;
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
let snapshotPayload;
|
|
1038
|
+
try {
|
|
1039
|
+
snapshotPayload = JSON.parse(await readTextFile(snapshotPath));
|
|
1040
|
+
} catch {
|
|
1041
|
+
fail('Invalid JSON in .agent-context/state/stack-research-snapshot.json');
|
|
1042
|
+
return;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
if (snapshotPayload?.deterministic === true) {
|
|
1046
|
+
pass('stack-research-snapshot.json declares deterministic: true');
|
|
1047
|
+
} else {
|
|
1048
|
+
fail('stack-research-snapshot.json must declare deterministic: true');
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
const generatedAtValue = String(snapshotPayload?.generatedAt || '');
|
|
1052
|
+
if (!Number.isNaN(Date.parse(generatedAtValue))) {
|
|
1053
|
+
pass('stack-research-snapshot.json includes valid generatedAt timestamp');
|
|
1054
|
+
} else {
|
|
1055
|
+
fail('stack-research-snapshot.json must include a valid generatedAt timestamp');
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
if (Array.isArray(snapshotPayload?.trustedRealtimeSources) && snapshotPayload.trustedRealtimeSources.length > 0) {
|
|
1059
|
+
pass('stack-research-snapshot.json includes trustedRealtimeSources');
|
|
1060
|
+
} else {
|
|
1061
|
+
fail('stack-research-snapshot.json must include at least one trustedRealtimeSources entry');
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
if (!Array.isArray(snapshotPayload?.stackSignals) || snapshotPayload.stackSignals.length === 0) {
|
|
1065
|
+
fail('stack-research-snapshot.json must include non-empty stackSignals array');
|
|
1066
|
+
return;
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
pass(`stack-research-snapshot.json includes ${snapshotPayload.stackSignals.length} stack signal entries`);
|
|
1070
|
+
|
|
1071
|
+
const invalidSignalEntries = snapshotPayload.stackSignals.filter((signalEntry) => {
|
|
1072
|
+
const hasStackName = typeof signalEntry?.stackFileName === 'string' && signalEntry.stackFileName.trim().length > 0;
|
|
1073
|
+
const hasMeasuredAt = !Number.isNaN(Date.parse(String(signalEntry?.measuredAt || '')));
|
|
1074
|
+
const metrics = signalEntry?.metrics || {};
|
|
1075
|
+
const hasValidMetrics = isNormalizedMetricValue(metrics.ecosystemMaturity)
|
|
1076
|
+
&& isNormalizedMetricValue(metrics.talentAvailability)
|
|
1077
|
+
&& isNormalizedMetricValue(metrics.deliveryVelocity);
|
|
1078
|
+
|
|
1079
|
+
return !(hasStackName && hasMeasuredAt && hasValidMetrics);
|
|
1080
|
+
});
|
|
1081
|
+
|
|
1082
|
+
if (invalidSignalEntries.length === 0) {
|
|
1083
|
+
pass('stack-research-snapshot.json stackSignals keep measurable metrics and timestamps');
|
|
1084
|
+
} else {
|
|
1085
|
+
fail(`stack-research-snapshot.json has invalid stackSignals entries: ${invalidSignalEntries.length}`);
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
|
|
931
1089
|
async function validateMcpConfiguration() {
|
|
932
1090
|
console.log('\nChecking MCP configuration...');
|
|
933
1091
|
|
|
@@ -1177,6 +1335,9 @@ async function main() {
|
|
|
1177
1335
|
await validateVersionConsistency();
|
|
1178
1336
|
await validateDocumentationFlow();
|
|
1179
1337
|
await validateTerminologyMapping();
|
|
1338
|
+
await validateDetectionTransparencyCoverage();
|
|
1339
|
+
await validateStackResearchEngineCoverage();
|
|
1340
|
+
await validateStackResearchSnapshotState();
|
|
1180
1341
|
await validateMcpConfiguration();
|
|
1181
1342
|
await validateHumanWritingGovernance();
|
|
1182
1343
|
await validateInstructionAdapters();
|